from fastapi import APIRouter, Depends, status, File, UploadFile, HTTPException, Form,Query
from typing import Optional
from sqlalchemy.orm import Session
from src.utils.db import get_db
from . import controller, schema
import os
import uuid
import shutil
from pathlib import Path
from src.utils.response import APIResponse
from typing import List
from src.apps.auth.controller import get_current_user
from itsdangerous import URLSafeSerializer
import httpx, os, secrets, time
from fastapi.responses import RedirectResponse, JSONResponse
from urllib.parse import urlencode

router = APIRouter(prefix="/master-accounts", tags=["Master Accounts"])

# Create Account
# BASE_URL = "http://localhost:8000"
BASE_URL = os.getenv("BASE_URL", "http://localhost:8000")
BASE_UI_URL = os.getenv("BASE_UI_URL", "http://localhost:5173")
BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", ".."))
STATIC_PATH = os.path.join(BASE_DIR, "menu_design", "designer", "static", "marketing", "images")
APP_ID = os.getenv("FB_APP_ID")
APP_SECRET = os.getenv("FB_APP_SECRET")
REDIRECT_URI = os.getenv("OAUTH_REDIRECT_URL")
SECRET_KEY = os.getenv("SECRET_KEY")

os.makedirs(STATIC_PATH, exist_ok=True)
signer = URLSafeSerializer(SECRET_KEY, salt="fb-oauth")
GRAPH = "https://graph.facebook.com/v20.0"

# Create a master account
@router.post("/", response_model=schema.MasterAccountOut,dependencies=[Depends(get_current_user)])
def create_master_account(
    social_media_name: Optional[str] = Form(None),
    account_type: Optional[str] = Form(None),
    icon_image: Optional[UploadFile] = File(None),
    db: Session = Depends(get_db)
):
    icon_url = None

    if icon_image:
        if icon_image.content_type not in ["image/png", "image/jpeg", "image/webp"]:
            raise HTTPException(status_code=400, detail="Unsupported image format")

        filename = f"{uuid.uuid4().hex}_{os.path.basename(icon_image.filename)}"
        file_path = os.path.join(STATIC_PATH, filename)

        try:
            with open(file_path, "wb") as buffer:
                shutil.copyfileobj(icon_image.file, buffer)
        except Exception as e:
            raise HTTPException(status_code=500, detail="Failed to save image")

        icon_url = f"{BASE_URL}/static/marketing/images/{filename}"

    data = schema.MasterAccountCreate(
        social_media_name=social_media_name,
        icon_image=icon_url,
        account_type=account_type
    )

    return controller.create_master_account_controller(data, db)


# Get a master account by ID
@router.get("/{id}", response_model=APIResponse[schema.MasterAccountOut], dependencies=[Depends(get_current_user)])
def get_one(id: int, db: Session = Depends(get_db)):
    try:
        result =  controller.get_master_account_controller(id, db)
        return APIResponse(
            success=True,
            message="Master account fetched successfully",
            data=result
        )
    except HTTPException as e:
        raise e
    except Exception as e:
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, 
                             detail=str(e))



# Get all master accounts
@router.get("/", response_model=APIResponse[List[schema.MasterAccountOut]], dependencies=[Depends(get_current_user)])
def get_all(db: Session = Depends(get_db)):
    try:
        result = controller.get_all_master_accounts_controller(db)
        return APIResponse(
            success=True,
            message="Master accounts fetched successfully",
            data=result
        )
    except HTTPException as e:
        raise e
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
    
# Update a master account
# Note: Using both PUT and PATCH for flexibility
@router.put("/{id}", response_model=schema.MasterAccountOut, dependencies=[Depends(get_current_user)])
@router.patch("/{id}", response_model=schema.MasterAccountOut, dependencies=[Depends(get_current_user)])
def update(id: int, data: schema.MasterAccountUpdate, db: Session = Depends(get_db)):
    return controller.update_master_account_controller(id, data, db)

# Delete a master account by ID
@router.delete("/{id}",dependencies=[Depends(get_current_user)])
def delete(id: int, db: Session = Depends(get_db)):
    return controller.delete_master_account_controller(id, db)


#--------------------------------------------Create Connected Accounts --------------------------------------------
connected_router = APIRouter(prefix="/connected-accounts", tags=["Connected Accounts"])

@connected_router.post("/",response_model =schema.ConnectedAccountOut, dependencies=[Depends(get_current_user)])
def create_connected_account(data:schema.ConnectedAccountCreate,db: Session = Depends(get_db)):
    try:
        return controller.create_connedted_account_controller(db,data)
    except HTTPException as e:
        raise HTTPException(status_code=500,details=f"Failed to insert {e}")
    


# @connected_router.post(
#     "/",
#     response_model=APIResponse[schema.ConnectedAccountOut],
#     dependencies=[Depends(get_current_user)]
# )
# def create_connected_account(data: schema.ConnectedAccountCreate, db: Session = Depends(get_db)):
#     try:
#         return controller.create_connedted_account_controller(db, data)
#     except HTTPException as e:
#         raise e



@connected_router.get("/{id}",response_model =APIResponse[schema.ConnectedAccountOut], dependencies=[Depends(get_current_user)])
def get_connected_account(id:int,db: Session = Depends(get_db)):
    conected_accounts = controller.get_all_connected_account_controller(db,id)
    return APIResponse(
        success=True,
        message="Connected accounts fetched successfully",
        data=conected_accounts
    )


@connected_router.get("/",response_model =APIResponse[List[schema.ConnectedAccountOut]], dependencies=[Depends(get_current_user)])
def get_connected_by_brach_id(branch_id: int = Query(..., alias="branch_id"),db: Session = Depends(get_db)):
    connected_account = controller.get_connected_account_by_branch_id_controller(db,branch_id)
    return APIResponse(
        success=True,
        message="Connected account fetched successfully",
        data=connected_account
    )
   

@connected_router.put("/{id}",response_model=schema.ConnectedAccountOut, dependencies=[Depends(get_current_user)])
@connected_router.patch("/{id}",response_model=schema.ConnectedAccountOut, dependencies=[Depends(get_current_user)])
def updated_connected_acount(id:int,data:schema.ConnectedAccountUpdate,db: Session = Depends(get_db)):
    return controller.updated_connected_account_controller(db, id, data)

# @connected_router.delete("/{id}",response_model =schema.ConnectedAccountOut, dependencies=[Depends(get_current_user)])

@connected_router.delete("/{id}",response_model=APIResponse[schema.DeleteAccountResponse] ,dependencies=[Depends(get_current_user)])
def deleted_connected_account(id: int, db: Session = Depends(get_db)):
    controller.deleted_connected_account_controller(db, id)
    return APIResponse(
        success=True,
        message="Connected account deleted successfully",
        data=None
    )

# -------------------------------------------------------------- FB AUTH LOGIC -----------------------------------------------------------------------------------
fb_auth_router = APIRouter(prefix="/auth/facebook", tags=["Social Media Auth"])
@fb_auth_router.get("/login")
async def fb_login():
    # CSRF state
    state = signer.dumps({"ts": int(time.time()), "nonce": secrets.token_urlsafe(16)})
    scope = "pages_show_list,pages_read_engagement,pages_manage_posts"
    params = {
        "client_id": APP_ID,
        "redirect_uri": REDIRECT_URI,
        "state": state,
        "response_type": "code",
        "scope": scope,
    }
    url = f"https://www.facebook.com/v20.0/dialog/oauth?{urlencode(params)}"
    return RedirectResponse(url)


@fb_auth_router.get("/callback")
async def fb_callback(code: str = None, state: str = None):
    # Verify state
    try:
        signer.loads(state)
    except Exception:
        raise HTTPException(status_code=400, detail="Invalid state")

    if not code:
        raise HTTPException(status_code=400, detail="Missing code")

    # Redirect back to your frontend app
    return RedirectResponse(f"{BASE_UI_URL}social-media/connect?provider=fb&code={code}&state={state}")

@fb_auth_router.post("/update-account",response_model=APIResponse[schema.FBUpdateConnectedAccountResponse], dependencies=[Depends(get_current_user)])
async def fb_update_auth(payload_data:schema.FBUpdateConnectedAccountRequest,db: Session = Depends(get_db)):
    # try:
    #     signer.loads(data.state)
    # except Exception:
    #     raise HTTPException(status_code=400, detail="Invalid state")
    
    # if not signer.code:
    #     raise HTTPException(status_code=400, detail="Missing code")
    
    print("data ============== ",payload_data)
    
    
    async with httpx.AsyncClient(timeout=20) as client:
        # Exchange code -> short-lived user access token
        token_url = f"{GRAPH}/oauth/access_token"
        r = await client.get(token_url, params={
            "client_id": APP_ID,
            "client_secret": APP_SECRET,
            "redirect_uri": REDIRECT_URI,
            "code": payload_data.code
        })
        r.raise_for_status()
        data = r.json()
        user_token = data["access_token"]

        # (Recommended) exchange for long‑lived user token
        r2 = await client.get(token_url, params={
            "grant_type": "fb_exchange_token",
            "client_id": APP_ID,
            "client_secret": APP_SECRET,
            "fb_exchange_token": user_token
        })
        r2.raise_for_status()
        ll = r2.json()
        user_token = ll["access_token"]
        expires_in = ll.get("expires_in", 60*60*24*60)

    expires_in = int(time.time()) + int(expires_in)
    
    async with httpx.AsyncClient(timeout=20) as client:
        # Get pages the person manages + page access tokens
        r = await client.get(f"{GRAPH}/me/accounts", params={
            "access_token": user_token,
            "fields": "id,name,category,access_token"
        })
        r.raise_for_status()
        pages = r.json().get("data", [])

    # cache page tokens
    for p in pages:
        if "access_token" in p:
            page_token = p["access_token"]
            page_id = p["id"]
            page_name = p["name"]
            connected_account_data = schema.ConnectedAccountCreate(
                master_account_id = payload_data.master_account_id,
                store_id = payload_data.store_id,
                branch_id = payload_data.branch_id,
                user_id = payload_data.user_id,
                token = page_token,
                external_account_id = page_id,
                external_account_name = page_name,
                expires_at = expires_in
            )
            try:
                created_account = controller.create_connedted_account_controller(db,connected_account_data)
            except HTTPException as e:
                raise HTTPException(status_code=500,details=f"Failed to insert {e}")
    
    # return final response here  
    return APIResponse(
        success=True,
        message="Connected accounts updated successfully",
        data=schema.FBUpdateConnectedAccountResponse(
            data=[schema.ConnectedAccountOut.model_validate(created_account)]
    )

    )      
            
            
            
