"""Stripe Connect account management routes."""

from fastapi import APIRouter, HTTPException, Header, Request
from pydantic import BaseModel, EmailStr, field_validator
from typing import Optional, Dict, Any, Literal
from agenticlypay.connect import ConnectManager
from agenticlypay.stripe_client import StripeClient
from agenticlypay.api.middleware.auth import resolve_email_from_auth
from agenticlypay.api.exceptions import (
    ValidationError,
    AuthenticationError,
    NotFoundError,
)
from agenticlypay.api.validators import validate_stripe_account_id

router = APIRouter()
connect_manager = ConnectManager()
stripe_client = StripeClient()


class CreateAccountRequest(BaseModel):
    """Request model for creating a developer account."""

    email: EmailStr
    country: str = "US"
    metadata: Optional[Dict[str, str]] = None

    @field_validator("country")
    @classmethod
    def validate_country(cls, v: str) -> str:
        if len(v) != 2:
            raise ValidationError("Country code must be 2 characters (ISO 3166-1 alpha-2)")
        return v.upper()


class CreateOnboardingLinkRequest(BaseModel):
    """Request model for creating an onboarding link."""

    account_id: str
    refresh_url: str
    return_url: str


class UpdateMetadataRequest(BaseModel):
    """Request model for updating account metadata."""

    account_id: str
    metadata: Dict[str, str]


class TaxInfoRequest(BaseModel):
    """Request model for tax information."""

    account_id: str
    name: str
    ssn: Optional[str] = None
    ein: Optional[str] = None
    address: str


class PayoutScheduleRequest(BaseModel):
    """Request model for configuring payout schedule."""

    account_id: str
    interval: Literal["manual", "daily", "weekly", "monthly"]
    monthly_anchor: Optional[int] = None
    weekly_anchor: Optional[Literal["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"]] = None


@router.post("/accounts")
async def create_account(request: CreateAccountRequest):
    """Create a new Stripe Connect account for a developer."""
    try:
        account = connect_manager.create_developer_account(
            email=request.email,
            country=request.country,
            metadata=request.metadata,
        )
        return {"success": True, "account": account}
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.get("/accounts/{account_id}")
async def get_account(request: Request, account_id: str):
    """Get account status.
    
    Note: Email query parameter is deprecated. Use API token authentication instead.
    """
    # Validate account ID format
    try:
        validate_stripe_account_id(account_id)
    except ValidationError:
        raise
    
    # Resolve email from auth (API token or header, no query param for security)
    email = resolve_email_from_auth(request)
    if not email:
        raise AuthenticationError("Authentication required. Use API token or X-Developer-Email header.")
    
    try:
        status = connect_manager.get_account_status(account_id, email)
        return {"success": True, "account": status}
    except Exception as e:
        raise NotFoundError(f"Account not found or access denied: {str(e)}")


@router.post("/onboarding")
async def create_onboarding_link(request: Request, onboarding_request: CreateOnboardingLinkRequest):
    """Create an onboarding link for a developer account."""
    # Validate account ID
    try:
        validate_stripe_account_id(onboarding_request.account_id)
    except ValidationError:
        raise
    
    # Resolve email from auth
    email = resolve_email_from_auth(request)
    if not email:
        raise AuthenticationError("Authentication required. Use API token or X-Developer-Email header.")
    
    try:
        link = connect_manager.create_onboarding_link(
            account_id=onboarding_request.account_id,
            refresh_url=onboarding_request.refresh_url,
            return_url=onboarding_request.return_url,
            email=email,
        )
        return {"success": True, "onboarding_link": link}
    except (ValidationError, NotFoundError):
        raise
    except Exception as e:
        raise ValidationError(f"Failed to create onboarding link: {str(e)}")


@router.put("/metadata")
async def update_metadata(request: UpdateMetadataRequest):
    """Update account metadata."""
    try:
        result = connect_manager.update_account_metadata(
            account_id=request.account_id, metadata=request.metadata
        )
        return {"success": True, "account": result}
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.post("/tax-info")
async def collect_tax_info(request: TaxInfoRequest):
    """Collect tax information for a developer."""
    try:
        tax_info = {
            "name": request.name,
            "ssn": request.ssn,
            "ein": request.ein,
            "address": request.address,
        }
        result = connect_manager.collect_tax_information(
            account_id=request.account_id, tax_info=tax_info
        )
        return {"success": True, "result": result}
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.post("/payout-schedule")
async def set_payout_schedule(request: Request, schedule_request: PayoutScheduleRequest):
    """Set payout schedule for a connected account."""
    # Validate account ID
    try:
        validate_stripe_account_id(schedule_request.account_id)
    except ValidationError:
        raise
    
    # Resolve email from auth
    email = resolve_email_from_auth(request)
    if not email:
        raise AuthenticationError("Authentication required. Use API token or X-Developer-Email header.")
    
    try:
        account = stripe_client.update_payout_schedule(
            account_id=schedule_request.account_id,
            interval=schedule_request.interval,
            monthly_anchor=schedule_request.monthly_anchor,
            weekly_anchor=schedule_request.weekly_anchor,
        )
        schedule = account.settings.payouts.schedule if hasattr(account.settings, "payouts") else None
        return {
            "success": True,
            "account_id": account.id,
            "payout_schedule": schedule,
        }
    except (ValidationError, NotFoundError):
        raise
    except Exception as e:
        raise ValidationError(f"Failed to update payout schedule: {str(e)}")
