import json
import os
import shutil
from typing import List, Optional
import uuid
from fastapi import APIRouter, Depends, File, Form, HTTPException, UploadFile, status,Query
from datetime import date

from pydantic import EmailStr

#db
from src.constants import CompanyPlanEnum
from src.core.database import get_db , get_datalake_client
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select,func
#models
from src.models.company import Company
from src.models.company_user import User
from src.models.application_user import ApplicationUser
#schemas
from .schemas import (
    AddCompanyUser,
    CompanyRegistration,
    CompanyUserCreate,
)

#global schemas
from src.schemas.application_user import CurrentApplicationUser
from src.schemas.compnay_user import CurrentCompanyUser
#global utils
from src.common.utils import (
    add_delete_update_application_user_access_check as application_user_access_check,
    init_dynamic_db
)
#global DP
from src.common.dependencies import get_current_application_user , get_current_company_user

#services
from .service import CompaniesManagement




companies_management_router = APIRouter(prefix="/companies/management", tags=["comppanies management module"])



@companies_management_router.post("/company-register/",status_code=status.HTTP_201_CREATED)
async def register_company(company_name: str = Form(...),
    legal_name: str = Form(...),
    bio: str = Form(...),
    address: str = Form(...),
    home_country: str = Form(...),
    has_branches: bool = Form(...),
    company_email: EmailStr = Form(...),
    company_phone_number: str = Form(...),
    users: str = Form(...),  # JSON string
    company_logo: UploadFile = File(...),
    collabrator:int=Form(...),
    bussiness_user:int=Form(...),
    view_only:int=Form(...),  
    plan_id:int=Form(...), name: str=Form(...), billing_cycle:str=Form(...), price :str=Form(...),

    db: AsyncSession = Depends(get_db),currentApplicationUser: CurrentApplicationUser = Depends(get_current_application_user)):
    try:
        
        has_permission = application_user_access_check(currentApplicationUser,action="add")
        if not has_permission:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="You do not have permission to Application a user."
            )
        

        UPLOAD_FOLDER = "uploads/company_logos"
        os.makedirs(UPLOAD_FOLDER, exist_ok=True)
        logo_filename = f"{company_name}_{company_logo.filename}"
        
        logo_path = os.path.join(UPLOAD_FOLDER, logo_filename)
        with open(logo_path, "wb") as buffer:
            shutil.copyfileobj(company_logo.file, buffer)
        
        try:
            users_parsed = json.loads(users)
            print("Parsed users:", users_parsed)  # check this output

            # Check type of first item
            if isinstance(users_parsed, list) and users_parsed and isinstance(users_parsed[0], str):
                # This means it's list of JSON strings, parse each again:
                users_parsed = [json.loads(u) for u in users_parsed]

            validated_users = [CompanyUserCreate(**user) for user in users_parsed]
        except Exception as e:
            raise HTTPException(status_code=422, detail=f"Invalid users format: {str(e)}")
                
        try:
            company_data = CompanyRegistration(
                company_name=company_name,
                legal_name=legal_name,
                bio=bio,
                address=address,
                home_country=home_country,
                company_logo_url=logo_path,
                has_branches=has_branches,
                company_email=company_email,
                company_phone_number=company_phone_number,
                users=validated_users,
                
            )
        except Exception as e:
            raise HTTPException(status_code=422, detail=f"Validation error: {str(e)}")
        result = await CompaniesManagement.register_company(
                company_info=company_data,
                collabrator=collabrator,
                bussiness_user=bussiness_user,
                view_only=view_only, plan_id=plan_id, name=name, billing_cycle=billing_cycle, price =price,
                db=db
            )
        print(result)
        company = result["company"]
        print("Company registered:", company)
        try:
            service = get_datalake_client()
            service.create_file_system(file_system=company_name)
            fs = service.get_file_system_client(company_name)        
            for f in ["bronze", "silver", "gold" , "inbound"]:
                fs.get_directory_client(f).create_directory()

            folders = ["account_customer_map", "accounts", "bookings", "budget", "budget_input", "chart_of_accounts",
                  "compensation", "cost_centers", "cost_centers_lookup", "customers", "customers_delta", "departments",
                  "departments_lookup","employees","entities","general_ledger_transactions","headcount_history",
                  "marketing_spend","oppurtunities","opportunity_booking_map","opportunity_campaign_attribution",
                  "producta","profit_centers","recruitment_pipeline","report_profit_and_loss","trial_balance","vendors"]

            created_folders = []
            for m in folders:
                path = f"inbound/{m}"
                try:
                    fs.get_directory_client(path).create_directory()
                    created_folders.append(path)
                except Exception:
                    created_folders.append(f"{path} (already exists)")


            print("medallion architecture created")
        except Exception as e:
            raise HTTPException(status_code=500 , detail= str(e))
        if hasattr(company, "db_name"):
            print("Initializing tenant database:", company.db_name)
            await init_tenant_db(company.db_name)
        else:
            raise HTTPException(status_code=500, detail="Company object missing 'db_name'")

        return result
    except HTTPException as e:
        raise e

@companies_management_router.put("/company-update/{company_id}", status_code=status.HTTP_200_OK)
async def update_company(
    company_id: str,
    company_name: Optional[str] = Form(None),
    legal_name: Optional[str] = Form(None),
    bio: Optional[str] = Form(None),
    address: Optional[str] = Form(None),
    home_country: Optional[str] = Form(None),
    has_branches: Optional[bool] = Form(None),
    company_email: Optional[EmailStr] = Form(None),
    company_phone_number: Optional[str] = Form(None),
    
    users: Optional[str] = Form(None),  # JSON string
    company_logo: Optional[UploadFile] = File(None),
    collabrator: Optional[int] = Form(None),
    bussiness_user: Optional[int] = Form(None),
    view_only: Optional[int] = Form(None),
    plan_id: Optional[int] = Form(None),
    name: Optional[str] = Form(None),
    billing_cycle: Optional[str] = Form(None),
    price: Optional[str] = Form(None),
    subscription_id: Optional[int] = Form(None),
    db: AsyncSession = Depends(get_db),
    current_user: CurrentApplicationUser = Depends(get_current_application_user)
):
    print("🔁 [API] Received request to update company:", company_id)

    has_permission = application_user_access_check(current_user, action="edit")
    print(has_permission)
    if not has_permission:
        print("🚫 User has no permission to edit")
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="You do not have permission to update company data."
        )

    logo_path = None
    if company_logo:
        print("🖼️ Handling logo upload...")
        UPLOAD_FOLDER = "uploads/company_logos"
        os.makedirs(UPLOAD_FOLDER, exist_ok=True)
        logo_filename = f"{company_name}_{company_logo.filename}"
        logo_path = os.path.join(UPLOAD_FOLDER, logo_filename)
        with open(logo_path, "wb") as buffer:
            shutil.copyfileobj(company_logo.file, buffer)
        print("✅ Logo saved at:", logo_path)

    try:
        validated_users = []
        if users:
            print("📦 Raw users JSON:", users)
            users_parsed = json.loads(users)

            if isinstance(users_parsed, list) and users_parsed and isinstance(users_parsed[0], str):
                print("🔄 Converting nested JSON strings inside users list...")
                users_parsed = [json.loads(u) for u in users_parsed]

            print("🧪 Validating users...")
            validated_users = [CompanyUserCreate(**user) for user in users_parsed]
            print(f"✅ Parsed {len(validated_users)} users")

        update_data = {
            "company_name": company_name,
            "legal_name": legal_name,
            "bio": bio,
            "address": address,
            "home_country": home_country,
            "company_logo_url": logo_path,
            "has_branches": has_branches,
            "company_email": company_email,
            "company_phone_number": company_phone_number,
           
            
            "collabrator": collabrator,
            "bussiness_user": bussiness_user,
            "view_only": view_only,
            "plan_id": plan_id,
            "name": name,
            "billing_cycle": billing_cycle,
            "price": price,
            "subscription_id": subscription_id
        }

        print("📋 Final update_data dict to pass:")
        # for k, v in update_data.items():
        #     print(f"  ├─ {k}: {v}")

        result = await CompaniesManagement.update_company_data(
            company_id=company_id,
            update_data=update_data,
            validated_users=validated_users,
            db=db
        )

        print("✅ Company update completed successfully")
        return result

    except HTTPException as e:
        print("❌ HTTPException occurred:", e.detail)
        raise e
    except Exception as e:
        print("💥 Unexpected error:", str(e))
        raise HTTPException(status_code=500, detail=str(e))

@companies_management_router.post("/add/company/user")
async def add_user(requestBody:AddCompanyUser,db: AsyncSession = Depends(get_db),currentApplicationUser: CurrentApplicationUser = Depends(get_current_application_user)):
    
    try:
        
        has_permission = application_user_access_check(currentApplicationUser,action="add")

        if not has_permission:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="You do not have permission to add a user."
            ) 
        result = await CompaniesManagement.add_user_to_company(
                user_info=requestBody,
                db=db
            )
        return result
    except HTTPException as e:
        raise e  


@companies_management_router.get("/companies/")
async def get_companies(
    page: int = Query(1, ge=1, description="Page number starting from 1"),                         
    limit: int = Query(10, ge=1, le=100, description="Items per page"),
    db: AsyncSession = Depends(get_db),
    currentApplicationUser: CurrentApplicationUser = Depends(get_current_application_user)
    ):

    try:

        result = await CompaniesManagement.get_companies(page=page,limit=limit,db=db)

        return result

    except HTTPException as e:
        raise e


@companies_management_router.post("/company/details")
async def get_company_details(
    company_id: str = Query(..., description="The ID of the company to fetch"),
    db: AsyncSession = Depends(get_db),
    currentApplicationUser: CurrentApplicationUser = Depends(get_current_application_user)
    ):

    try:
        result =  await CompaniesManagement.get_company_details(company_id=company_id,db=db)
        return result
    except HTTPException as e:
        raise e
 
@companies_management_router.post("/company/activate")
async def activate_company(
    company_id: str = Query(..., description="The ID of the company to fetch"),
    db: AsyncSession = Depends(get_db),
    currentApplicationUser: CurrentApplicationUser = Depends(get_current_application_user)
    ):
    
     try:
         
        has_permission = application_user_access_check(currentApplicationUser,action="add")

        if not has_permission:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="You do not have permission to add a user."
            )
        
        result = await CompaniesManagement.activate_company(company_id=company_id,db=db)

        return result
        
     
     except HTTPException as e:
         raise e
     
@companies_management_router.post("/company/deactivate")
async def deactivate_company(
    company_id: str = Query(..., description="The ID of the company to fetch"),
    db: AsyncSession = Depends(get_db),
    currentApplicationUser: CurrentApplicationUser = Depends(get_current_application_user)
    ):
    
     try:
         
        has_permission = application_user_access_check(currentApplicationUser,action="add")

        if not has_permission:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="You do not have permission to add a user."
            )
        
        result = await CompaniesManagement.deactivate_company(company_id=company_id,db=db)

        return result
        
     
     except HTTPException as e:
         raise e
     

@companies_management_router.get("/company-search")
async def company_search(
    search_query: str = Query(..., description="Search by company name, legal name, or email"),
    page: int = Query(1, ge=1, description="Page number"),
    limit: int = Query(10, ge=1, le=100, description="Number of results per page"),
    db: AsyncSession = Depends(get_db),
    currentApplicationUser: CurrentApplicationUser = Depends(get_current_application_user)
):
    
    try:
        result = await CompaniesManagement.company_search(
            search_query=search_query,
            page=page,
            limit=limit,
            db=db
            )

        return result
    except HTTPException as e:
        raise e

@companies_management_router.get("/company/admin/password-reset/")
async def reset_company_admin_password(
    user_id: str = Query(..., description="company IT admin user ID"),
    company_id: str = Query(..., description="The ID of the company"),
    db: AsyncSession = Depends(get_db),
    currentApplicationUser: CurrentApplicationUser = Depends(get_current_application_user)
    ):

     try:
         
        has_permission = application_user_access_check(currentApplicationUser,action="add")

        if not has_permission:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="You do not have permission to add a user."
            )
        
        result = await CompaniesManagement.reset_company_admin_password(company_id=company_id,admin_id=user_id,db=db)

        return result
        
     
     except HTTPException as e:
         raise e
     

@companies_management_router.post("/company/user/activate-deactivate/")
async def company_user_activate_deactivate(
    user_id: str = Query(..., description="company IT admin user ID"),
    company_id: str = Query(..., description="The ID of the company"),
    db: AsyncSession = Depends(get_db),
    currentApplicationUser: CurrentApplicationUser = Depends(get_current_application_user)
    ):

     try:
         
        has_permission = application_user_access_check(currentApplicationUser,action="add")

        if not has_permission:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="You do not have permission to add a user."
            )
        
        result = await CompaniesManagement.company_user_activate_deactivate(company_id=company_id,user_id=user_id,db=db)

        return result
        
     
     except HTTPException as e:
         raise e
     

from src.core.database import Base

def get_model_table_names():
    return list(Base.metadata.tables.keys())


@companies_management_router.post("/database/")
async def  init_tenant_db(database_name: str):
    
    db_url = f"postgresql+asyncpg://avnadmin:AVNS_As15bncmWPRJZ26soQA@pg-185d6b1c-mavengroup-9e06.l.aivencloud.com:19481/{database_name}"
   # db_url = f"postgresql+asyncpg://postgre:Pankaj@123@127.0.0.1:5432/{database_name}"

    skip_tables = ["companies", "application_users",
    "subscriptions",
    "user_roles",

]

    created_tables = await init_dynamic_db(db_url, tables_to_skip=skip_tables)
    return {
        "status": "initialized",
        "tables_created": created_tables
    }

@companies_management_router.post("/file/upload")
async def file_upload(data_type :str = Form(...),
                      file :UploadFile = File(...),
                      currentcompany :CurrentCompanyUser = Depends(get_current_company_user)                    
                      ):
    
    company_name = currentcompany.company_name
    print(currentcompany , "currentcompany")


    # company_name = "infotech"
    print(company_name)
    try:
        service = get_datalake_client()

        # Get  container
        try:
            fs = service.get_file_system_client(company_name)
            fs.get_file_system_properties()
        except Exception as e:
            raise HTTPException(status_code=500 , detail=str(e))
            
        folder_path = f"inbound/{data_type}"

        directory_client = fs.get_directory_client(folder_path)
        try:
            directory_client.get_directory_properties()
        except Exception as e:
            raise HTTPException(status_code=500 , detail=str(e))

        file_path = f"{folder_path}/{file.filename}"

        file_bytes = await file.read()

        file_client = fs.get_file_client(file_path)
        file_client.upload_data(file_bytes, overwrite=True)

        return {
            "file": file.filename,
            "path": file_path,
            "status" : "file uploaded"

        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
    
    
