from typing import Optional
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.params import Query
from pydantic import BaseModel
from requests import Session

from src.constants import CompanyPlanEnum

#local schemas
from .schemas import  (
    CompanyUserLogin,
    CompanyUserPasswordResetRequest,
    CompanyUserRestPassword,
    AppuserLoginRequest,
    DemoBookingRequest,
    DepartmentCreate,
    DepartmentUpdate,
    DepartmentResponse,
    InquiryRequest,
    PaginatedBlogResponse,
    RoleCreate,
    RoleUpdate,
    RoleResponse,
    RoleDepartmentCreate,
    RoleDepartmentUpdate,
    RoleDepartmentResponse,
    ModuleCreate,
    ModuleUpdate,
    ModuleResponse,
    SubscriptionCreate,
    SubscriptionPlanCreate,
    SubscriptionPlanUpdate,
    SubscriptionPlanResponse,
    PermissionCreate,
    PermissionUpdate,
    PermissionResponse,
    SubscriptionResponse,
    SubscriptionUpdate,
    UpdateSubscriptionPlanCreate,
    UserRoleCreate,
    UserRoleResponse,
    UserRoleUpdate, 
    

)

#global schemas
from src.schemas.compnay_user import CurrentCompanyUser

#db 
from src.core.database import get_db
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select


#global models
from src.models.company import BillingCycle, Blog, BlogStatusEnum, Company, DemoBooking, Inquiry, Module, SubscriptionPlan
from src.models.company_user import User
from src.models.application_user import ApplicationUser



#global utils
from src.common.utils import (
    add_delete_update_company_user_access_check as check_company_user_access,
)
#global dependencies
from src.common.dependencies import get_current_company_user,get_current_application_user


#service
from .service import CompanyUserAuthService
from .service import ApplicationUserAuthService


company_auth_router = APIRouter(prefix="/company/user/auth", tags=["company auth module"])

@company_auth_router.post("/login")
async def company_user_login(requestBody: CompanyUserLogin, db: AsyncSession = Depends(get_db)):
    try:
        result = await CompanyUserAuthService.user_login(
            email=requestBody.email,
            password=requestBody.password,
            db=db
        )
        return result
    except HTTPException as e: # rise only HTTPException other Exception will take care by global Exception handler
        raise e


@company_auth_router.post("/request-reset-password")
async def request_reset_password(requestBody: CompanyUserPasswordResetRequest, db: AsyncSession = Depends(get_db)):

    try:
        result = await CompanyUserAuthService.request_reset_password(
            email=requestBody.email,
            db=db
        )
        return result
    except HTTPException as e: 
        raise e
        

@company_auth_router.post("/reset-password/{encrypted_token}")
async def reset_password(encrypted_token: str, requestBody: CompanyUserRestPassword, db: AsyncSession = Depends(get_db)):
    try:
        result = await CompanyUserAuthService.reset_password(
        encrypted_token,
        requestBody.new_password,
        db=db
        )
        return result
    except HTTPException as e: 
        raise e
   


@company_auth_router.get("/2fa/setup/{two_FA_setup_token}")
async def setup_2fa(two_FA_setup_token:str,db: AsyncSession = Depends(get_db)):

    try:

        currentCompanyUser = get_current_company_user(token=two_FA_setup_token)
        user_id = currentCompanyUser.user_id
        result = await CompanyUserAuthService.setup_2fa(user_id,db=db)
        return result
    except HTTPException as e: 
        raise e





@company_auth_router.post("/2fa/verify/{user_id}/{token}")
async def verify_2fa(user_id:str,token: str,db: AsyncSession = Depends(get_db)):
    
    print(user_id,token)
    try:
        result = await CompanyUserAuthService.verify_2fa(
            user_id,
            token,
            db=db
        )
        return result
    except HTTPException as e: 
        raise e


@company_auth_router.post("/2fa/login/{two_FA_token}/{two_FA_code}")
async def login_2fa(two_FA_token:str,two_FA_code: str,db: AsyncSession = Depends(get_db)):

    try:
        currentCompanyUser = get_current_company_user(two_FA_token)
        user_id = currentCompanyUser.user_id
        result = await CompanyUserAuthService.login_2fa(
            user_id,
            two_FA_code,
            db=db
        )
        return result
    except HTTPException as e: 
        raise e
    


@company_auth_router.post("/enable-disable/2fa/{user_id}")
async def enable_disable_two_factor_auth(user_id:str,db: AsyncSession = Depends(get_db),currentCompanyUser: CurrentCompanyUser = Depends(get_current_company_user)):


    try:
    
        has_permission = check_company_user_access(currentCompanyUser,action="update")

        if not has_permission:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="You do not have permission for Two factor auth module contact IT admin."
            )
        
        current_company_user_company_id = currentCompanyUser.company_id
        user_id = user_id
        result = await CompanyUserAuthService.enable_disable_two_factor_auth(
                user_id= user_id,
                current_company_user_company_id = current_company_user_company_id,
                db=db
            )
        return result
    except HTTPException as e: 
        raise e

    

    




#Application auth users routes
application_auth_router = APIRouter(prefix="/application/user/auth", tags=["Application auth module"])

@application_auth_router.post("/login")
async def app_user_login(requestBody:AppuserLoginRequest,db:AsyncSession = Depends(get_db)):
    try:
        result = await ApplicationUserAuthService.user_login(
            email=requestBody.email,
            password=requestBody.password,
            db=db
        )
        return result
    except HTTPException as e: # rise only HTTPException other Exception will take care by global Exception handler
        raise e


@company_auth_router.get("/restrict")
def get_available_endpoints(user: CurrentCompanyUser = Depends(get_current_company_user)):
    plan_access_map = {
        CompanyPlanEnum.BASIC: [
            "/api/v1/company/user/auth/login",
            "/api/v1/company/user/auth/request-reset-password",
            "/api/v1/company/user/auth/reset-password/{encrypted_token}",
            "/api/v1/company/management/company-users/",
            "/api/v1/company/financial/financial-overview",
            "/api/v1/company/financial/profit_and_loss",
            "/api/v1/company/financial/balance_sheet",
            "/api/v1/company/financial/cashflow",
            "/api/v1/company/financial/accounts_receivable",
            "/api/v1/company/financial/accounts_payable",
            "/api/v1/company/financial/revenue",
            "/api/v1/company/financial/operation_expense",
        ],
        CompanyPlanEnum.EXPERIENCED: [
            "/api/v1/company/financial/upload-gl/",
            "/api/v1/company/financial/gl-master",
            "/api/v1/company/financial/gl-entries",
            "/api/v1/company/financial/analytics/expenses",
            "/api/v1/company/financial/analytics/revenue",
            "/api/v1/company/financial/analytics/profit-analysis",
            "/api/v1/company/financial/analytics/cash-flow",
            "/api/v1/company/financial/metrics/calculate",
            "/api/v1/company/financial/widgets",
            "/api/v1/company/financial/KPI/widgets",
            "/api/v1/company/financial/overview/widgets",
            "/api/v1/company/financial/metric/all",
            "/api/v1/company/financial/derived-metric/all",
            "/api/v1/forecast/compare/{year}",
            "/api/v1/ai/chat",
        ],
        CompanyPlanEnum.PROFICIENT: [
            "/api/v1/company/HR_and_CRM/hr/details/",
            "/api/v1/company/HR_and_CRM/crm/details/",
            "/api/v1/company/HR_and_CRM/api/v1/payroll/report",
            "/api/v1/forecast/{scenario}",
            "/api/v1/company/financial/fixed_assets",
            "/api/v1/company/financial/financial-overview/balance-sheet-comparison",
            "/api/v1/company/financial/financial-overview/accounts-receivable-payable",
            "/api/v1/company/financial/analytics/revenue-comparison",
            "/api/v1/company/HR_and_CRM/crm/integration-history",
            "/api/v1/company/HR_and_CRM/hr/integration-history",
        ]
    }

    all_accessible = plan_access_map.get(CompanyPlanEnum.BASIC, [])
    if user.plan == CompanyPlanEnum.EXPERIENCED:
        all_accessible += plan_access_map[CompanyPlanEnum.EXPERIENCED]
    elif user.plan == CompanyPlanEnum.PROFICIENT:
        all_accessible += plan_access_map[CompanyPlanEnum.EXPERIENCED] + plan_access_map[CompanyPlanEnum.PROFICIENT]

    return {
        "plan": user.plan,
        "accessible_endpoints": list(set(all_accessible))  # remove duplicates
    }
from src.auth import service

# ---------- Departments ----------
@company_auth_router.post("/departments/")
async def create_department(dept: DepartmentCreate, db: Session = Depends(get_db)):
    return await service.add_department(db, name=dept.name, description=dept.description)

@company_auth_router.get("/departments/")
async def read_departments(db: Session = Depends(get_db)):
    # Change to async
    dept = await service.get_all_departments(db)
    if not dept:
        raise HTTPException(status_code=404, detail="Departments not found")
    return dept

@company_auth_router.put("/departments/{department_id}", response_model=None)
async def update_department(department_id: int, dept_in: DepartmentUpdate, db: Session = Depends(get_db)):
    dept = await service.update_department(db, department_id, name=dept_in.name, description=dept_in.description)
    if not dept:
        raise HTTPException(status_code=404, detail="Department not found")
    return dept

@company_auth_router.delete("/departments/{department_id}", response_model=dict)
async def delete_department(department_id: int, db: Session = Depends(get_db)):
    success = await service.delete_department(db, department_id)
    if not success:
        raise HTTPException(status_code=404, detail="Department not found")
    return {"message": "Department deleted successfully"}


# ---------- Roles ----------
@company_auth_router.post("/roles/", response_model=None)
async def create_role(role: RoleCreate, db: Session = Depends(get_db)):
    return await service.add_role(db, name=role.name, description=role.description)

@company_auth_router.get("/roles/")
async def read_roles(db: Session = Depends(get_db)):
    roles = await service.get_all_roles(db)
    if not roles:
        raise HTTPException(status_code=404, detail="Roles not found")
    return roles

@company_auth_router.put("/roles/{role_id}", response_model=None)
async def update_role(role_id: int, role_in: RoleUpdate, db: Session = Depends(get_db)):
    role = await service.update_role(db, role_id, name=role_in.name, description=role_in.description)
    if not role:
        raise HTTPException(status_code=404, detail="Role not found")
    return role

@company_auth_router.delete("/roles/{role_id}", response_model=dict)
async def delete_role(role_id: int, db: Session = Depends(get_db)):
    success = await service.delete_role(db, role_id)
    if not success:
        raise HTTPException(status_code=404, detail="Role not found")
    return {"message": "Role deleted successfully"}


# ---------- RoleDepartment ----------
@company_auth_router.post("/role_departments/", response_model=None)
async def create_role_department(rd: RoleDepartmentCreate, db: Session = Depends(get_db)):
    return await service.add_role_department(db, role_id=rd.role_id, department_id=rd.department_id)

@company_auth_router.get("/role_departments/")
async def read_role_departments(db: Session = Depends(get_db)):
    rd = await service.get_all_role_departments(db)
    if not rd:
        raise HTTPException(status_code=404, detail="RoleDepartments not found")
    return rd

@company_auth_router.put("/role_departments/{rd_id}", response_model=None)
async def update_role_department(rd_id: int, rd_in: RoleDepartmentUpdate, db: Session = Depends(get_db)):
    rd = await service.update_role_department(db, rd_id, role_id=rd_in.role_id, department_id=rd_in.department_id)
    if not rd:
        raise HTTPException(status_code=404, detail="RoleDepartment not found")
    return rd

@company_auth_router.delete("/role_departments/{rd_id}", response_model=dict)
async def delete_role_department(rd_id: int, db: Session = Depends(get_db)):
    success = await service.delete_role_department(db, rd_id)
    if not success:
        raise HTTPException(status_code=404, detail="RoleDepartment not found")
    return {"message": "RoleDepartment deleted successfully"}


# ---------- Modules ----------
@company_auth_router.post("/modules/", response_model=None)
async def create_module(module: ModuleCreate, db: Session = Depends(get_db)):
    return await service.add_module(db, name=module.name, description=module.description)

@company_auth_router.get("/modules/")
async def read_modules(db: Session = Depends(get_db)):
    modules = await service.get_all_modules(db)
    if not modules:
        raise HTTPException(status_code=404, detail="Modules not found")
    return modules

@company_auth_router.put("/modules/{module_id}", response_model=None)
async def update_module(module_id: int, module_in: ModuleUpdate, db: Session = Depends(get_db)):
    module = await service.update_module(db, module_id, name=module_in.name, description=module_in.description)
    if not module:
        raise HTTPException(status_code=404, detail="Module not found")
    return module

@company_auth_router.delete("/modules/{module_id}", response_model=dict)
async def delete_module(module_id: int, db: Session = Depends(get_db)):
    success = await service.delete_module(db, module_id)
    if not success:
        raise HTTPException(status_code=404, detail="Module not found")
    return {"message": "Module deleted successfully"}


# ---------- Subscriptions ----------
@company_auth_router.get("/subscriptions/")
async def read_subscriptions(db: Session = Depends(get_db)):
    subscriptions = await service.get_all_subscriptions(db)
    if not subscriptions:
        raise HTTPException(status_code=404, detail="Subscriptions not found")
    return subscriptions

@company_auth_router.delete("/subscriptions/{subscription_id}", response_model=dict)
async def delete_subscription(subscription_id: int, db: Session = Depends(get_db)):
    success = await service.delete_subscription(db, subscription_id)
    if not success:
        raise HTTPException(status_code=404, detail="Subscription not found")
    return {"message": "Subscription deleted successfully"}
@company_auth_router.post("/subscriptions/", response_model=None)
async def create_subscription(subscription: SubscriptionCreate, db: Session = Depends(get_db)):
    return await service.add_subscription(
        db,
        company_id=subscription.company_id,
        plan_id=subscription.plan_id,
        start_date=subscription.start_date,
        end_date=subscription.end_date,
        is_active=subscription.is_active
    )
@company_auth_router.put("/subscriptions/{subscription_id}", response_model=None)
async def update_subscription(subscription_id: int, subscription_in: SubscriptionUpdate, db: Session = Depends(get_db)):
    subscription = await service.update_subscription(
        db,
        subscription_id,
        company_id=subscription_in.company_id,
        plan_id=subscription_in.plan_id,
        start_date=subscription_in.start_date,
        end_date=subscription_in.end_date,
        is_active=subscription_in.is_active
    )
    if not subscription:
        raise HTTPException(status_code=404, detail="Subscription not found")
    return subscription
from typing import List
from .schemas import ModuleSchema

# controller.py

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from typing import List


# POST - create package plan
@company_auth_router.post("/package-plans/", response_model=None)
async def create_package_plan(
    data: SubscriptionPlanCreate,billing_cycle: Optional[BillingCycle],
    db: AsyncSession = Depends(get_db),
):
    
    plan = await service.add_package(
        db=db,
        name=data.name,
        modules=data.modules,
        collabrator=data.collabrator,
        bussiness_user=data.bussiness_user,
        view_only=data.view_only,
        user_limit=data.user_limit,
        billing_cycle=billing_cycle,
        price=data.price
    )
    return plan
# GET - list all package plans
@company_auth_router.get("/package-plans/", response_model=None)
async def get_all_package_plans(db: AsyncSession = Depends(get_db)):
    return await service.get_all_package_plans(db)
@company_auth_router.get("/package-plans/{plan_id}", response_model=None)
async def get_single_package_plan(plan_id: int, db: AsyncSession = Depends(get_db)):
    plan = await service.get_package_plan_by_id(db, plan_id)
    if not plan:
        raise HTTPException(status_code=404, detail="Package plan not found")
    return plan
@company_auth_router.put("/package-plans/{plan_id}", response_model=None)
async def update_package_plan(plan_id: int, data: UpdateSubscriptionPlanCreate, db: AsyncSession = Depends(get_db)):
    updated_plan = await service.update_package_plan(db, plan_id, data,data.billing_cycle)
    return updated_plan
@company_auth_router.delete("/package-plans/{plan_id}")
async def delete_package_plan(plan_id: int, db: AsyncSession = Depends(get_db)):
    success = await service.delete_package_plan(db, plan_id)
    if not success:
        raise HTTPException(status_code=404, detail="Package plan not found or could not be deleted")
    return {"detail": "Package plan deleted successfully"}


# ROI Calculation Endpoints
from typing import Literal
from pydantic import BaseModel


class ROIInput(BaseModel):
    annualRevenue: float
    annualPayrollCosts: float
    annualNonPayrollCosts: float
    financePeople: int
    otherPeople: int
    timeSpent: float  # percentage (e.g., 25)
    biToolsCost: float
    packageType: Literal['Starter', 'Professional', 'Enterprise']


class ROIOutput(BaseModel):
    marginGrowth: int
    costSavings: int
    timeReduction: int
    estimatedSavings: int


class ROIResult(BaseModel):
    year1: dict
    year2: dict
    year3: dict
    total: dict

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
import re
from decimal import Decimal, InvalidOperation

def normalize_price(price) -> int:
    try:
        # Case 1: if it's already a number (int, float, Decimal)
        if isinstance(price, (int, float, Decimal)):
            return int(Decimal(price))  # float -> Decimal -> int (safe)

        # Case 2: if it's a string with symbols (e.g., "$26,500.00")
        if isinstance(price, str):
            cleaned = re.sub(r"[^\d.]", "", price)  # remove $, commas, etc.
            return int(Decimal(cleaned))  # convert to Decimal then int

    except (InvalidOperation, ValueError):
        raise ValueError(f"Invalid price value: {price!r}")

    raise TypeError(f"Unsupported type for price: {type(price)}")

async def get_subscription_price_by_name(session: AsyncSession, plan_name: str) -> int:
    stmt = select(SubscriptionPlan).where(SubscriptionPlan.name == plan_name)
    result = await session.execute(stmt)
    plan = result.scalar_one_or_none()

    if plan is None: 
        raise ValueError(f"Subscription plan '{plan_name}' not found.")
    
    return normalize_price(plan.price)  # assuming price is stored as string, else remove int()

# Helper functions for calculations

def calculate_roi(inputs: ROIInput) -> ROIOutput:
    # Handle zero revenue safely
    if inputs.annualRevenue == 0:
        margin_growth = 0
    else:
        margin_growth = inputs.annualRevenue * 0.02 * (
            (inputs.annualRevenue - inputs.annualPayrollCosts) / inputs.annualRevenue
        )

    # Ensure payroll and non-payroll costs are non-negative
    payroll_costs = max(inputs.annualPayrollCosts, 0)
    non_payroll_costs = max(inputs.annualNonPayrollCosts, 0)

    cost_savings = (payroll_costs + non_payroll_costs) * 0.015

    # Ensure people counts and time spent are non-negative
    finance_people = max(inputs.financePeople, 0)
    other_people = max(inputs.otherPeople, 0)
    time_spent = max(inputs.timeSpent, 0)

    time_reduction = (
        (finance_people * time_spent) * 60000 * 0.20 +
        (other_people * time_spent) * 85000 * 0.30
    )

    estimated_savings = margin_growth + cost_savings + time_reduction

    return ROIOutput(
        marginGrowth=round(margin_growth),
        costSavings=round(cost_savings),
        timeReduction=round(time_reduction),
        estimatedSavings=round(estimated_savings)
    )


def calculate_roi_over_3_years(inputs: ROIOutput, planprice: int) -> ROIResult:
    # Safety: Make sure cost is not negative
    planprice = max(planprice, 0)

    year1_cost = planprice + 15000 + 12500
    year2_cost = planprice + 15000
    year3_cost = year2_cost

    total_cost = year1_cost + year2_cost + year3_cost
    est_savings = inputs.estimatedSavings

    # Safe division function
    def safe_div(numerator, denominator):
        return round(numerator / denominator, 1) if denominator != 0 else 0.0

    return ROIResult(
        year1={
            "cost": round(year1_cost),
            "roi": safe_div(est_savings, year1_cost)
        },
        year2={
            "cost": round(year2_cost),
            "roi": safe_div(est_savings, year2_cost)
        },
        year3={
            "cost": round(year3_cost),
            "roi": safe_div(est_savings, year3_cost)
        },
        total={
            "cost": round(total_cost),
            "roi": safe_div(est_savings * 3, total_cost)
        }
    )

# API endpoints

# @company_auth_router.post("/calculate/outputs", response_model=ROIOutput)
# def get_outputs(data: ROIInput):
#     return calculate_outputs(data)


# @company_auth_router.post("/calculate/roi", response_model=ROIResult)
# def get_roi(data: ROIInput):
#     outputs = calculate_outputs(data)
#     return calculate_roi(data, outputs)

@company_auth_router.post("/calculator_of_roi/", response_model=None)
async def calculator_roi(data: ROIInput, db: AsyncSession = Depends(get_db)):
    data.timeSpent = data.timeSpent / 100
    roidata=calculate_roi(data)
    plan_price = await get_subscription_price_by_name(db, data.packageType)
    roi_result = calculate_roi_over_3_years(roidata, plan_price)
    return {
        "outputs": roidata,
        "roi": roi_result
    }
website_api_router = APIRouter(prefix="/blogs", tags=["Blogs"])



@website_api_router.post("/book-demo", summary="Book a product demo")
async def book_demo(payload: DemoBookingRequest, db: Session = Depends(get_db)):
    try:
        # Basic email format validation
        if not re.match(r"[^@]+@[^@]+\.[^@]+", payload.email):
            raise ValueError("Invalid email format")
        

        # Create DB model instance
        booking = DemoBooking(
            name=payload.name,
            company=payload.company,
            email=payload.email,
            interests=payload.interests,
            message=payload.message,
        )

        # Save to DB
        db.add(booking)
        await db.commit()
        await db.refresh(booking)

        return {
            "status": "success",
            "message": f"Demo booked successfully for {payload.name}.",
            "booking_id": booking.id,
        }
    except ValueError as ve:
        raise HTTPException(status_code=400, detail=str(ve))
    except Exception as e:
        await db.rollback()
        raise HTTPException(status_code=500, detail="Internal server error")

@application_auth_router.get("/demo-bookings/", summary="Get all demo bookings")
async def get_all_demo_bookings(db: AsyncSession = Depends(get_db)):
    try:
         result = await db.execute(select(DemoBooking))
         bookings = result.scalars().all()
         return bookings
    except Exception as e:
        raise HTTPException(status_code=500, detail="Internal server error")
   




@website_api_router.post("/send-inquiry", summary="Submit a plan inquiry")
async def send_inquiry(payload: InquiryRequest, db: Session = Depends(get_db)):
    # Check if the subscription plan exists
    try:
        if not re.match(r"[^@]+@[^@]+\.[^@]+", payload.email):
            raise ValueError("Invalid email format")
        result = await db.execute(
            select(SubscriptionPlan).where(SubscriptionPlan.subscription_plan_id == payload.subscription_plan_id)
        )
        plan = result.scalar_one_or_none() # Use scalar_one_or_none for single result or None 
            
        if not plan:
            raise HTTPException(status_code=404, detail="Subscription plan not found")

        # Save inquiry
        inquiry = Inquiry(
            email=payload.email,
            phone=payload.phone,
            company=payload.company,
            additional_message=payload.additional_message,
            subscription_plan_id=payload.subscription_plan_id
        )
        db.add(inquiry)
        await db.commit()
        await db.refresh(inquiry)

        return {
            "status": "success",
            "message": "Inquiry submitted successfully.",
            "inquiry_id": inquiry.id,
            "linked_plan": plan.name
        }
    except ValueError as ve:
        print(ve)
        raise HTTPException(status_code=400, detail=str(ve))
    except HTTPException as he:
        print(he)
        raise he
    except Exception as e:
        await db.rollback()
        print(e)
        raise HTTPException(status_code=500, detail="Internal server error")
from sqlalchemy.orm import joinedload

@application_auth_router.get("/inquiries/", summary="Get all inquiries")
async def get_all_inquiries(db: AsyncSession = Depends(get_db)):
    result = await db.execute(
        select(Inquiry).options(joinedload(Inquiry.subscription_plan))
    )
    inquiries = result.scalars().all()
    return inquiries
@application_auth_router.get("/inquiries/{inquiry_id}", summary="Get inquiry by ID")
async def get_inquiry_by_id(inquiry_id: int, db: AsyncSession = Depends(get_db)):
    result = await db.execute(
        select(Inquiry).options(joinedload(Inquiry.subscription_plan)).where(Inquiry.id == inquiry_id)
    )
    inquiry = result.scalar_one_or_none()

    if not inquiry:
        raise HTTPException(status_code=404, detail="Inquiry not found")

    return inquiry


from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, update, delete
from typing import List

from .schemas import BlogCreate, BlogUpdate, BlogOut




from fastapi import APIRouter, Depends, Form
from typing import List, Optional
from sqlalchemy.ext.asyncio import AsyncSession


from fastapi import UploadFile, File
import os
import shutil
import re

def sanitize_folder_name(name):
    # Replace all invalid characters with an underscore or hyphen
    return re.sub(r'[\\/*?:"<>| ]', "_", name)

@website_api_router.post("/", response_model=BlogOut)
async def create_blog(
    title: str = Form(...),
    content: str = Form(...),
    author: str = Form(...),
    status: BlogStatusEnum = Form(default=BlogStatusEnum.DRAFT),
    tags: Optional[List[str]|str] = Form(default_factory=list),
    image: UploadFile = File(...),  # image file upload
    db: AsyncSession = Depends(get_db),
    meta_title :str = Form(...),    #new field
    meta_description : str = Form(...), #new field 
    alt_text :str = Form(...)
):
    try:
        # Optional: ensure it's valid UTF-8 (catch binary errors)
        content.encode("utf-8")
    except UnicodeEncodeError:
        raise HTTPException(status_code=400, detail="Content must be UTF-8 text")
    # Create folder path: ./blog/<title>/
    base_path = "blog"
    blog_folder = os.path.join(base_path, title.replace(" ", "_"))  # sanitize title for folder name
    sanitized_title = sanitize_folder_name(title)
    blog_folder = os.path.join("blog", sanitized_title)
    os.makedirs(blog_folder, exist_ok=True)

    # Save the uploaded image file to folder
    image_path = os.path.join(blog_folder, image.filename.strip())
    
    with open(image_path, "wb") as buffer:
        shutil.copyfileobj(image.file, buffer)
    
    if isinstance(tags, str):
        import json
        try:
            # Try parse JSON list
            tags = json.loads(tags)
        except:
            # Fallback: split by space or comma
            tags = [t.strip() for t in tags.replace(",", " ").split() if t.strip()]

    # Prepare the payload including image path (you might want to save relative path or URL)
    payload = BlogCreate(
        title=title,
        content=content,
        author=author,
        status=status,
        tags=tags,
        image=image_path , # make sure BlogCreate has image_path attribute
        meta_title = meta_title,
        meta_description = meta_description,
        alt_text = alt_text
    )

    return await service.create_blog(payload, db)


from fastapi import UploadFile, File
@website_api_router.put("/{id}", response_model=BlogOut)
async def update_blog(
    id: int,
    title: str = Form(...),
    content: str = Form(...),
    author: str = Form(...),
    status: BlogStatusEnum = Form(default=BlogStatusEnum.DRAFT),
    tags: Optional[List[str] | str] = Form(default_factory=list),
    image: Optional[UploadFile] = File(None),
    db: AsyncSession = Depends(get_db),
    meta_title :str = Form(...),    #new field
    meta_description : str = Form(...), #new field
    alt_text :str = Form(...)  # new Field
):
    # Step 1: Fetch the blog
    blog = await service.get_blog_by_id(id, db)
    if not blog:
        raise HTTPException(status_code=404, detail="Blog not found")

    # Step 2: Delete old image if new one is provided
    if image:
        # if blog.image_path and os.path.exists(blog.image_path):
        #     os.remove(blog.image_path)
        image_path  = rf"{os.getcwd()}/{blog.image}" 
        if os.path.exists(image_path):
            os.remove(image_path)


        blog_folder = os.path.join("blog", title.replace(" ", "_"))
        os.makedirs(blog_folder, exist_ok=True)

        image_path = os.path.join(blog_folder, image.filename)
        with open(image_path, "wb") as buffer:
            shutil.copyfileobj(image.file, buffer)
    else:
        image_path = blog.image  # retain old image path
    if isinstance(tags, str):
        import json
        try:
            # Try parse JSON list
            tags = json.loads(tags)
        except:
            # Fallback: split by space or comma
            tags = [t.strip() for t in tags.replace(",", " ").split() if t.strip()]

    # Step 3: Build the update payload
    payload = BlogUpdate(
        title=title,
        content=content,
        author=author,
        status=status,
        tags=tags,
        image=image_path,
        meta_title = meta_title,
        meta_description = meta_description , 
        alt_text = alt_text

    )

    # Step 4: Update blog
    return await service.update_blog(id, payload, db)

@website_api_router.delete("/{id}")
async def delete_blog(id: int, db: AsyncSession = Depends(get_db)):
    blog = await service.get_blog_by_id(id, db)
    if not blog:
        raise HTTPException(status_code=404, detail="Blog not found")

    if blog.image and os.path.exists(blog.image):
        os.remove(blog.image)
    
    return await service.delete_blog(id, db)

@website_api_router.put("/{id}/status", response_model=BlogOut)
async def update_blog_status(
    id: int,
    status: BlogStatusEnum= Query(),  # validated enum input
    db: AsyncSession = Depends(get_db)
):
    return await service.update_blog_status(id, status, db)


@website_api_router.get("/", response_model=PaginatedBlogResponse)
async def get_all_blogs(
    status: Optional[BlogStatusEnum] = Query(None),
    author: Optional[str] = Query(None),
    tag: Optional[str] = Query(None),  # filter blogs containing this tag
    limit: int = Query(10, gt=0),
    offset: int = Query(0, ge=0),
    db: AsyncSession = Depends(get_db),
):
    return await service.get_filtered_blogs(
        db=db, status=status, author=author, tag=tag, limit=limit, offset=offset
    )


@website_api_router.get("/{id}", response_model=BlogOut)
async def get_blog(id: int, db: AsyncSession = Depends(get_db)):
    return await service.get_blog_by_id(id, db)

@website_api_router.get("/published/", response_model=List[BlogOut])
async def get_published_blogs(db: AsyncSession = Depends(get_db)):
    return await service.get_blogs_by_status(BlogStatusEnum.PUBLISHED, db)

@website_api_router.get("/archived/", response_model=List[BlogOut])
async def get_archived_blogs(db: AsyncSession = Depends(get_db)):
    return await service.get_blogs_by_status(BlogStatusEnum.ARCHIVED, db)
