"""
Client Management API Endpoints
"""
from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func
from sqlalchemy.orm import selectinload
from pydantic import BaseModel, EmailStr
from typing import Optional, List
from datetime import datetime
import secrets

from app.database import get_db
from app.auth.dependencies import get_current_user, get_current_admin
from app.models.client import Client, ClientStatus
from app.models.user import User
from app.models.subscription import Subscription

router = APIRouter()


# Request/Response Models
class ClientCreate(BaseModel):
    company_name: str
    company_email: EmailStr
    company_phone: Optional[str] = None
    company_website: Optional[str] = None
    industry: Optional[str] = None
    company_size: Optional[str] = None
    address_line1: Optional[str] = None
    city: Optional[str] = None
    state: Optional[str] = None
    country: Optional[str] = "India"
    postal_code: Optional[str] = None
    gstin: Optional[str] = None


class ClientUpdate(BaseModel):
    company_name: Optional[str] = None
    company_phone: Optional[str] = None
    company_website: Optional[str] = None
    company_logo_url: Optional[str] = None
    industry: Optional[str] = None
    company_size: Optional[str] = None
    address_line1: Optional[str] = None
    address_line2: Optional[str] = None
    city: Optional[str] = None
    state: Optional[str] = None
    country: Optional[str] = None
    postal_code: Optional[str] = None
    gstin: Optional[str] = None
    pan: Optional[str] = None
    billing_email: Optional[str] = None
    status: Optional[str] = None


class ClientResponse(BaseModel):
    id: int
    company_name: str
    company_email: str
    company_phone: Optional[str]
    company_website: Optional[str]
    company_logo_url: Optional[str]
    industry: Optional[str]
    company_size: Optional[str]
    status: str
    is_verified: bool
    city: Optional[str]
    state: Optional[str]
    country: Optional[str]
    referral_code: Optional[str]
    created_at: datetime

    class Config:
        from_attributes = True


class ClientDetailResponse(ClientResponse):
    address_line1: Optional[str]
    address_line2: Optional[str]
    postal_code: Optional[str]
    gstin: Optional[str]
    pan: Optional[str]
    billing_email: Optional[str]
    billing_address: Optional[str]
    users_count: int
    active_subscriptions: int


class ClientListResponse(BaseModel):
    clients: List[ClientResponse]
    total: int
    page: int
    page_size: int


@router.get("", response_model=ClientListResponse)
async def list_clients(
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    search: Optional[str] = None,
    status: Optional[str] = None,
    industry: Optional[str] = None,
    current_user: User = Depends(get_current_admin),
    db: AsyncSession = Depends(get_db)
):
    """
    List all clients (Admin only)
    """
    query = select(Client)

    # Apply filters
    if search:
        query = query.where(
            (Client.company_name.ilike(f"%{search}%")) |
            (Client.company_email.ilike(f"%{search}%"))
        )

    if status:
        query = query.where(Client.status == status)

    if industry:
        query = query.where(Client.industry == industry)

    # Get total count
    count_query = select(func.count()).select_from(query.subquery())
    total = await db.scalar(count_query)

    # Apply pagination
    query = query.offset((page - 1) * page_size).limit(page_size)
    query = query.order_by(Client.created_at.desc())

    result = await db.execute(query)
    clients = result.scalars().all()

    return ClientListResponse(
        clients=[ClientResponse(
            id=c.id,
            company_name=c.company_name,
            company_email=c.company_email,
            company_phone=c.company_phone,
            company_website=c.company_website,
            company_logo_url=c.company_logo_url,
            industry=c.industry,
            company_size=c.company_size,
            status=c.status,
            is_verified=c.is_verified,
            city=c.city,
            state=c.state,
            country=c.country,
            referral_code=c.referral_code,
            created_at=c.created_at
        ) for c in clients],
        total=total,
        page=page,
        page_size=page_size
    )


@router.get("/me", response_model=ClientDetailResponse)
async def get_my_client(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    Get current user's client/company details
    """
    if not current_user.client_id:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="No client associated with this user"
        )

    result = await db.execute(
        select(Client)
        .options(selectinload(Client.users), selectinload(Client.subscriptions))
        .where(Client.id == current_user.client_id)
    )
    client = result.scalar_one_or_none()

    if not client:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Client not found"
        )

    active_subs = len([s for s in client.subscriptions if s.is_active])

    return ClientDetailResponse(
        id=client.id,
        company_name=client.company_name,
        company_email=client.company_email,
        company_phone=client.company_phone,
        company_website=client.company_website,
        company_logo_url=client.company_logo_url,
        industry=client.industry,
        company_size=client.company_size,
        status=client.status,
        is_verified=client.is_verified,
        city=client.city,
        state=client.state,
        country=client.country,
        referral_code=client.referral_code,
        created_at=client.created_at,
        address_line1=client.address_line1,
        address_line2=client.address_line2,
        postal_code=client.postal_code,
        gstin=client.gstin,
        pan=client.pan,
        billing_email=client.billing_email,
        billing_address=client.billing_address,
        users_count=len(client.users),
        active_subscriptions=active_subs
    )


@router.get("/{client_id}", response_model=ClientDetailResponse)
async def get_client(
    client_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    Get a specific client by ID
    """
    # Check permissions
    if not current_user.is_admin and current_user.client_id != client_id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Access denied"
        )

    result = await db.execute(
        select(Client)
        .options(selectinload(Client.users), selectinload(Client.subscriptions))
        .where(Client.id == client_id)
    )
    client = result.scalar_one_or_none()

    if not client:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Client not found"
        )

    active_subs = len([s for s in client.subscriptions if s.is_active])

    return ClientDetailResponse(
        id=client.id,
        company_name=client.company_name,
        company_email=client.company_email,
        company_phone=client.company_phone,
        company_website=client.company_website,
        company_logo_url=client.company_logo_url,
        industry=client.industry,
        company_size=client.company_size,
        status=client.status,
        is_verified=client.is_verified,
        city=client.city,
        state=client.state,
        country=client.country,
        referral_code=client.referral_code,
        created_at=client.created_at,
        address_line1=client.address_line1,
        address_line2=client.address_line2,
        postal_code=client.postal_code,
        gstin=client.gstin,
        pan=client.pan,
        billing_email=client.billing_email,
        billing_address=client.billing_address,
        users_count=len(client.users),
        active_subscriptions=active_subs
    )


@router.post("", response_model=ClientResponse, status_code=status.HTTP_201_CREATED)
async def create_client(
    data: ClientCreate,
    current_user: User = Depends(get_current_admin),
    db: AsyncSession = Depends(get_db)
):
    """
    Create a new client (Admin only)
    """
    # Check if email already exists
    result = await db.execute(select(Client).where(Client.company_email == data.company_email))
    if result.scalar_one_or_none():
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Client with this email already exists"
        )

    # Generate referral code
    referral_code = secrets.token_hex(4).upper()

    client = Client(
        company_name=data.company_name,
        company_email=data.company_email,
        company_phone=data.company_phone,
        company_website=data.company_website,
        industry=data.industry,
        company_size=data.company_size,
        address_line1=data.address_line1,
        city=data.city,
        state=data.state,
        country=data.country,
        postal_code=data.postal_code,
        gstin=data.gstin,
        status=ClientStatus.TRIAL,
        referral_code=referral_code
    )
    db.add(client)
    await db.commit()
    await db.refresh(client)

    return ClientResponse(
        id=client.id,
        company_name=client.company_name,
        company_email=client.company_email,
        company_phone=client.company_phone,
        company_website=client.company_website,
        company_logo_url=client.company_logo_url,
        industry=client.industry,
        company_size=client.company_size,
        status=client.status,
        is_verified=client.is_verified,
        city=client.city,
        state=client.state,
        country=client.country,
        referral_code=client.referral_code,
        created_at=client.created_at
    )


@router.put("/{client_id}", response_model=ClientResponse)
async def update_client(
    client_id: int,
    data: ClientUpdate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    Update a client
    """
    # Check permissions
    if not current_user.is_admin and current_user.client_id != client_id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Access denied"
        )

    result = await db.execute(select(Client).where(Client.id == client_id))
    client = result.scalar_one_or_none()

    if not client:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Client not found"
        )

    # Update fields
    update_fields = data.model_dump(exclude_unset=True)

    # Only admins can change status
    if "status" in update_fields and not current_user.is_admin:
        del update_fields["status"]

    for field, value in update_fields.items():
        setattr(client, field, value)

    await db.commit()
    await db.refresh(client)

    return ClientResponse(
        id=client.id,
        company_name=client.company_name,
        company_email=client.company_email,
        company_phone=client.company_phone,
        company_website=client.company_website,
        company_logo_url=client.company_logo_url,
        industry=client.industry,
        company_size=client.company_size,
        status=client.status,
        is_verified=client.is_verified,
        city=client.city,
        state=client.state,
        country=client.country,
        referral_code=client.referral_code,
        created_at=client.created_at
    )


@router.delete("/{client_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_client(
    client_id: int,
    current_user: User = Depends(get_current_admin),
    db: AsyncSession = Depends(get_db)
):
    """
    Delete a client (Admin only)
    """
    result = await db.execute(select(Client).where(Client.id == client_id))
    client = result.scalar_one_or_none()

    if not client:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Client not found"
        )

    await db.delete(client)
    await db.commit()


@router.get("/{client_id}/users", response_model=List[dict])
async def get_client_users(
    client_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    Get all users for a client
    """
    # Check permissions
    if not current_user.is_admin and current_user.client_id != client_id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Access denied"
        )

    result = await db.execute(select(User).where(User.client_id == client_id))
    users = result.scalars().all()

    return [{
        "id": u.id,
        "email": u.email,
        "name": u.name,
        "role": u.role.value,
        "is_active": u.is_active,
        "created_at": u.created_at
    } for u in users]


@router.get("/{client_id}/subscriptions", response_model=List[dict])
async def get_client_subscriptions(
    client_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    Get all subscriptions for a client
    """
    # Check permissions
    if not current_user.is_admin and current_user.client_id != client_id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Access denied"
        )

    result = await db.execute(select(Subscription).where(Subscription.client_id == client_id))
    subscriptions = result.scalars().all()

    return [{
        "id": s.id,
        "service_type": s.service_type,
        "plan_name": s.plan_name,
        "plan_tier": s.plan_tier,
        "status": s.status,
        "price_monthly": float(s.price_monthly),
        "start_date": s.start_date,
        "end_date": s.end_date,
        "is_active": s.is_active
    } for s in subscriptions]
