"""
API REST para operações assíncronas do Sistema de Barbearia.
Cálculo de slots dinâmicos, criação de agendamentos, fechamento de comandas e comissões.
"""
from fastapi import APIRouter, HTTPException, Depends
from pydantic import BaseModel
from typing import Optional, List
from datetime import datetime, timedelta
from app.database import get_db

router = APIRouter(prefix="/api", tags=["API"])

class AppointmentCreate(BaseModel):
    barbershop_id: int
    service_id: int
    barber_id: int # 0 para qualquer barbeiro
    appointment_date: str # YYYY-MM-DD
    start_time: str # HH:MM
    client_name: str
    client_phone: str
    notes: Optional[str] = None

class StatusUpdate(BaseModel):
    status: str

class OrderCreate(BaseModel):
    barbershop_id: int
    appointment_id: Optional[int] = None
    barber_id: int
    client_name: str
    service_id: Optional[int] = None
    product_id: Optional[int] = None
    discount: Optional[float] = 0.0
    payment_method: str = "pix"

class AdvanceCreate(BaseModel):
    barbershop_id: int
    barber_id: int
    amount: float
    description: str

class SubscriptionCreate(BaseModel):
    barbershop_id: int
    client_id: int
    plan_id: int

class ShopUpdate(BaseModel):
    name: str
    phone: str
    opening_time: str
    closing_time: str
    pix_key: Optional[str] = None
    pix_deposit_amount: Optional[float] = 0.0

class ServiceCreate(BaseModel):
    barbershop_id: int
    name: str
    description: Optional[str] = None
    price: float
    duration_minutes: int = 30

class BarberCreate(BaseModel):
    barbershop_id: int
    name: str
    phone: str
    commission_rate: float = 0.50
    avatar_color: str = "#d97706"


@router.get("/slots")
def get_available_slots(shop_id: int, date: str, barber_id: int = 0, service_id: int = 0):
    """
    Calcula os horários livres com base no funcionamento da barbearia,
    duração do serviço e agendamentos já existentes.
    """
    with get_db() as conn:
        cursor = conn.cursor()
        
        # 1. Obter dados da barbearia
        cursor.execute("SELECT opening_time, closing_time, slot_interval FROM barbershops WHERE id = ?", (shop_id,))
        shop = cursor.fetchone()
        if not shop:
            raise HTTPException(status_code=404, detail="Barbearia não encontrada")

        open_str = shop["opening_time"] or "09:00"
        close_str = shop["closing_time"] or "20:00"
        slot_interval = shop["slot_interval"] or 30

        # Duração do serviço
        duration = 30
        if service_id > 0:
            cursor.execute("SELECT duration_minutes FROM services WHERE id = ?", (service_id,))
            s = cursor.fetchone()
            if s:
                duration = s["duration_minutes"]

        # Gerar todos os slots do dia
        open_dt = datetime.strptime(open_str, "%H:%M")
        close_dt = datetime.strptime(close_str, "%H:%M")

        all_slots = []
        cur = open_dt
        while cur + timedelta(minutes=duration) <= close_dt:
            all_slots.append(cur.strftime("%H:%M"))
            cur += timedelta(minutes=slot_interval)

        # 2. Buscar agendamentos que colidem no dia
        if barber_id > 0:
            cursor.execute("""
            SELECT start_time, end_time FROM appointments
            WHERE barbershop_id = ? AND barber_id = ? AND appointment_date = ? 
            AND status NOT IN ('cancelado', 'falta')
            """, (shop_id, barber_id, date))
            busy_slots = [r["start_time"] for r in cursor.fetchall()]
        else:
            # Qualquer profissional: horário só fica ocupado se TODOS os barbeiros estiverem ocupados
            cursor.execute("SELECT COUNT(*) FROM barbers WHERE barbershop_id = ? AND is_active = 1", (shop_id,))
            total_barbers = cursor.fetchone()[0] or 1

            cursor.execute("""
            SELECT start_time, COUNT(*) as count FROM appointments
            WHERE barbershop_id = ? AND appointment_date = ? 
            AND status NOT IN ('cancelado', 'falta')
            GROUP BY start_time
            """, (shop_id, date))
            busy_slots = [r["start_time"] for r in cursor.fetchall() if r["count"] >= total_barbers]

        # Se for o dia de hoje, não permitir agendar horários que já passaram
        now = datetime.now()
        is_today = (date == now.strftime("%Y-%m-%d"))

        available = []
        for slot in all_slots:
            if slot in busy_slots:
                continue
            if is_today:
                slot_time = datetime.strptime(slot, "%H:%M").time()
                if slot_time <= now.time():
                    continue
            available.append(slot)

        return {"date": date, "slots": available}


@router.post("/appointments")
def create_appointment(data: AppointmentCreate):
    """
    Cria agendamento, cadastra ou atualiza o cliente automaticamente pelo telefone,
    e calcula o horário de término.
    """
    with get_db() as conn:
        cursor = conn.cursor()

        # 1. Buscar serviço para obter duração e preço
        cursor.execute("SELECT name, price, duration_minutes FROM services WHERE id = ?", (data.service_id,))
        service = cursor.fetchone()
        if not service:
            raise HTTPException(status_code=404, detail="Serviço não encontrado")

        duration = service["duration_minutes"]
        total_price = service["price"]

        # Calcular end_time
        start_dt = datetime.strptime(data.start_time, "%H:%M")
        end_time = (start_dt + timedelta(minutes=duration)).strftime("%H:%M")

        # 2. Selecionar barbeiro caso venha 0 ("Qualquer disponível")
        barber_id = data.barber_id
        if barber_id == 0:
            cursor.execute("""
            SELECT b.id FROM barbers b
            WHERE b.barbershop_id = ? AND b.is_active = 1
            AND b.id NOT IN (
                SELECT barber_id FROM appointments 
                WHERE barbershop_id = ? AND appointment_date = ? AND start_time = ? AND status NOT IN ('cancelado', 'falta')
            )
            LIMIT 1
            """, (data.barbershop_id, data.barbershop_id, data.appointment_date, data.start_time))
            row = cursor.fetchone()
            if row:
                barber_id = row[0]
            else:
                # Pega o primeiro barbeiro ativo
                cursor.execute("SELECT id FROM barbers WHERE barbershop_id = ? AND is_active = 1 LIMIT 1", (data.barbershop_id,))
                b_first = cursor.fetchone()
                barber_id = b_first[0] if b_first else 1

        # 3. Upsert do Cliente pelo WhatsApp (Zero atrito - sem senha!)
        clean_phone = "".join(filter(str.isdigit, data.client_phone))
        cursor.execute("SELECT id, total_visits FROM clients WHERE barbershop_id = ? AND phone = ?", (data.barbershop_id, clean_phone))
        client_row = cursor.fetchone()

        if client_row:
            client_id = client_row["id"]
            cursor.execute("""
            UPDATE clients SET name = ?, total_visits = total_visits + 1, last_visit_at = ?
            WHERE id = ?
            """, (data.client_name, data.appointment_date, client_id))
        else:
            cursor.execute("""
            INSERT INTO clients (barbershop_id, name, phone, total_visits, last_visit_at)
            VALUES (?, ?, ?, 1, ?)
            """, (data.barbershop_id, data.client_name, clean_phone, data.appointment_date))
            client_id = cursor.lastrowid

        # 4. Inserir Agendamento
        cursor.execute("""
        INSERT INTO appointments (barbershop_id, barber_id, client_id, service_id, appointment_date, start_time, end_time, status, total_amount, notes)
        VALUES (?, ?, ?, ?, ?, ?, ?, 'confirmado', ?, ?)
        """, (data.barbershop_id, barber_id, client_id, data.service_id, data.appointment_date, data.start_time, end_time, total_price, data.notes))
        appt_id = cursor.lastrowid

        # 5. Registrar disparo de mensagem WhatsApp
        cursor.execute("SELECT name FROM barbers WHERE id = ?", (barber_id,))
        barber_name = cursor.fetchone()["name"]

        zap_msg = f"Fala {data.client_name}! Seu agendamento para {service['name']} com {barber_name} no dia {data.appointment_date} às {data.start_time} foi confirmado com sucesso!"
        cursor.execute("""
        INSERT INTO whatsapp_messages (barbershop_id, appointment_id, client_phone, client_name, message_type, message_text, status)
        VALUES (?, ?, ?, ?, 'confirmacao', ?, 'enviada')
        """, (data.barbershop_id, appt_id, clean_phone, data.client_name, zap_msg))

        return {"success": True, "appointment_id": appt_id}


@router.patch("/appointments/{appt_id}/status")
def update_appointment_status(appt_id: int, data: StatusUpdate):
    with get_db() as conn:
        cursor = conn.cursor()
        cursor.execute("UPDATE appointments SET status = ? WHERE id = ?", (data.status, appt_id))
        if cursor.rowcount == 0:
            raise HTTPException(status_code=404, detail="Agendamento não encontrado")
        return {"success": True, "status": data.status}


@router.post("/orders")
def create_order(data: OrderCreate):
    """
    Fecha a comanda no caixa:
    - Adiciona serviços e produtos.
    - Calcula comissão do barbeiro (50% serviço + 10% produtos).
    - Calcula o lucro líquido da barbearia.
    - Atualiza o status do agendamento para 'concluido' se vinculado.
    """
    with get_db() as conn:
        cursor = conn.cursor()

        # Obter comissão do barbeiro
        cursor.execute("SELECT commission_rate FROM barbers WHERE id = ?", (data.barber_id,))
        barber = cursor.fetchone()
        comm_rate = barber["commission_rate"] if barber else 0.50

        total_service = 0.0
        service_name = None
        if data.service_id and data.service_id > 0:
            cursor.execute("SELECT name, price FROM services WHERE id = ?", (data.service_id,))
            s = cursor.fetchone()
            if s:
                total_service = s["price"]
                service_name = s["name"]

        total_product = 0.0
        product_name = None
        if data.product_id and data.product_id > 0:
            cursor.execute("SELECT name, price, stock_quantity FROM products WHERE id = ?", (data.product_id,))
            p = cursor.fetchone()
            if p:
                total_product = p["price"]
                product_name = p["name"]
                # Abater do estoque
                cursor.execute("UPDATE products SET stock_quantity = MAX(0, stock_quantity - 1) WHERE id = ?", (data.product_id,))

        final_amount = max(0.0, (total_service + total_product) - data.discount)

        # Regra de comissão: taxa configurada sobre serviços + 10% de produtos
        barber_commission = (total_service * comm_rate) + (total_product * 0.10)
        house_net = final_amount - barber_commission

        items = []
        if service_name:
            items.append(service_name)
        if product_name:
            items.append(f"1x {product_name}")
        items_summary = " + ".join(items) if items else "Atendimento avulso"

        # Inserir Pedido / Comanda
        cursor.execute("""
        INSERT INTO orders (
            barbershop_id, appointment_id, barber_id, client_name,
            total_services, total_products, discount, final_amount,
            payment_method, payment_status, barber_commission_amount, house_net_amount, items_summary
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'pago', ?, ?, ?)
        """, (
            data.barbershop_id, data.appointment_id, data.barber_id, data.client_name,
            total_service, total_product, data.discount, final_amount,
            data.payment_method, barber_commission, house_net, items_summary
        ))
        order_id = cursor.lastrowid

        # Inserir Itens
        if service_name:
            cursor.execute("INSERT INTO order_items (order_id, item_type, item_id, item_name, price, quantity) VALUES (?, 'service', ?, ?, ?, 1)", (order_id, data.service_id, service_name, total_service))
        if product_name:
            cursor.execute("INSERT INTO order_items (order_id, item_type, item_id, item_name, price, quantity) VALUES (?, 'product', ?, ?, ?, 1)", (order_id, data.product_id, product_name, total_product))

        # Se houver agendamento vinculado, marcar como concluído
        if data.appointment_id and data.appointment_id > 0:
            cursor.execute("UPDATE appointments SET status = 'concluido' WHERE id = ?", (data.appointment_id,))

        return {"success": True, "order_id": order_id, "final_amount": final_amount, "barber_commission": barber_commission}


@router.post("/advances")
def create_advance(data: AdvanceCreate):
    with get_db() as conn:
        cursor = conn.cursor()
        today = datetime.now().strftime("%Y-%m-%d")
        cursor.execute("""
        INSERT INTO barber_advances (barbershop_id, barber_id, amount, description, date)
        VALUES (?, ?, ?, ?, ?)
        """, (data.barbershop_id, data.barber_id, data.amount, data.description, today))
        return {"success": True, "advance_id": cursor.lastrowid}


@router.post("/subscriptions")
def create_subscription(data: SubscriptionCreate):
    with get_db() as conn:
        cursor = conn.cursor()
        now = datetime.now()
        started = now.strftime("%Y-%m-%d")
        next_bill = (now + timedelta(days=30)).strftime("%Y-%m-%d")
        cursor.execute("""
        INSERT INTO client_subscriptions (barbershop_id, client_id, plan_id, status, cuts_used_this_month, started_at, next_billing_date)
        VALUES (?, ?, ?, 'ativo', 0, ?, ?)
        """, (data.barbershop_id, data.client_id, data.plan_id, started, next_bill))
        return {"success": True, "subscription_id": cursor.lastrowid}


@router.post("/subscriptions/{sub_id}/use-cut")
def use_subscription_cut(sub_id: int):
    with get_db() as conn:
        cursor = conn.cursor()
        cursor.execute("UPDATE client_subscriptions SET cuts_used_this_month = cuts_used_this_month + 1 WHERE id = ?", (sub_id,))
        return {"success": True}


@router.put("/shop/{shop_id}")
def update_shop(shop_id: int, data: ShopUpdate):
    with get_db() as conn:
        cursor = conn.cursor()
        cursor.execute("""
        UPDATE barbershops SET name = ?, phone = ?, opening_time = ?, closing_time = ?, pix_key = ?, pix_deposit_amount = ?
        WHERE id = ?
        """, (data.name, data.phone, data.opening_time, data.closing_time, data.pix_key, data.pix_deposit_amount, shop_id))
        return {"success": True}


@router.post("/services")
def create_service(data: ServiceCreate):
    with get_db() as conn:
        cursor = conn.cursor()
        cursor.execute("""
        INSERT INTO services (barbershop_id, name, description, price, duration_minutes)
        VALUES (?, ?, ?, ?, ?)
        """, (data.barbershop_id, data.name, data.description, data.price, data.duration_minutes))
        return {"success": True, "service_id": cursor.lastrowid}


@router.post("/barbers")
def create_barber(data: BarberCreate):
    with get_db() as conn:
        cursor = conn.cursor()

        # Validação do limite de profissionais segundo o plano contratado da barbearia
        cursor.execute("SELECT max_barbers, plan_tier FROM barbershops WHERE id = ?", (data.barbershop_id,))
        shop = cursor.fetchone()
        if not shop:
            raise HTTPException(status_code=404, detail="Barbearia não encontrada")

        cursor.execute("SELECT COUNT(*) FROM barbers WHERE barbershop_id = ? AND is_active = 1", (data.barbershop_id,))
        total = cursor.fetchone()[0]

        if total >= shop["max_barbers"]:
            raise HTTPException(
                status_code=400,
                detail=f"Limite atingido: O plano {shop['plan_tier'].upper()} permite até {shop['max_barbers']} profissional(is). Faça upgrade do seu plano para adicionar mais barbeiros à equipe."
            )

        cursor.execute("""
        INSERT INTO barbers (barbershop_id, name, phone, commission_rate, avatar_color)
        VALUES (?, ?, ?, ?, ?)
        """, (data.barbershop_id, data.name, data.phone, data.commission_rate, data.avatar_color))
        return {"success": True, "barber_id": cursor.lastrowid}


# --- ENDPOINTS DO MASTER ADMIN (GESTOR DO SAAS) ---

class MasterShopCreate(BaseModel):
    name: str
    slug: str
    phone: str
    email: str
    password: str = "123456"
    plan_tier: str = "basico"

class MasterPlanUpdate(BaseModel):
    plan_tier: str

@router.post("/master/shops")
def master_create_shop(data: MasterShopCreate):
    tier_limits = {
        "basico": 1,
        "intermediario": 5,
        "profissional": 999
    }
    max_b = tier_limits.get(data.plan_tier, 1)

    clean_slug = data.slug.strip().lower().replace(" ", "-")

    with get_db() as conn:
        cursor = conn.cursor()
        
        # Verificar se slug já existe
        cursor.execute("SELECT id FROM barbershops WHERE slug = ?", (clean_slug,))
        if cursor.fetchone():
            raise HTTPException(status_code=400, detail="Este link/slug já está em uso por outra barbearia.")

        cursor.execute("""
        INSERT INTO barbershops (name, slug, phone, email, password, plan_tier, max_barbers)
        VALUES (?, ?, ?, ?, ?, ?, ?)
        """, (data.name, clean_slug, data.phone, data.email, data.password, data.plan_tier, max_b))
        new_id = cursor.lastrowid

        # Criar serviços padrões iniciais
        cursor.execute("INSERT INTO services (barbershop_id, name, price, duration_minutes) VALUES (?, 'Corte Degradê / Social', 45.00, 35)", (new_id,))
        cursor.execute("INSERT INTO services (barbershop_id, name, price, duration_minutes) VALUES (?, 'Barba Completa', 35.00, 30)", (new_id,))
        cursor.execute("INSERT INTO services (barbershop_id, name, price, duration_minutes) VALUES (?, 'Combo Cabelo + Barba', 70.00, 50)", (new_id,))

        # Criar o primeiro barbeiro padrão
        cursor.execute("INSERT INTO barbers (barbershop_id, name, phone, avatar_color, commission_rate) VALUES (?, ?, ?, '#d97706', 0.50)", (new_id, data.name, data.phone))

        return {"success": True, "shop_id": new_id, "slug": clean_slug}


@router.patch("/master/shops/{shop_id}/plan")
def master_update_shop_plan(shop_id: int, data: MasterPlanUpdate):
    tier_limits = {
        "basico": 1,
        "intermediario": 5,
        "profissional": 999
    }
    max_b = tier_limits.get(data.plan_tier, 1)

    with get_db() as conn:
        cursor = conn.cursor()
        cursor.execute("UPDATE barbershops SET plan_tier = ?, max_barbers = ? WHERE id = ?", (data.plan_tier, max_b, shop_id))
        if cursor.rowcount == 0:
            raise HTTPException(status_code=404, detail="Barbearia não encontrada")
        return {"success": True, "plan_tier": data.plan_tier, "max_barbers": max_b}


@router.patch("/master/shops/{shop_id}/status")
def master_toggle_shop_status(shop_id: int):
    with get_db() as conn:
        cursor = conn.cursor()
        cursor.execute("UPDATE barbershops SET is_active = CASE WHEN is_active = 1 THEN 0 ELSE 1 END WHERE id = ?", (shop_id,))
        cursor.execute("SELECT is_active FROM barbershops WHERE id = ?", (shop_id,))
        row = cursor.fetchone()
        return {"success": True, "is_active": row["is_active"]}

