"""Product catalog and opportunity item routes.

Moved from app.admin_dashboard in v4.7.2. The handlers still reuse
legacy helpers to keep this refactor behavior-preserving.
"""
from fastapi import APIRouter
from decimal import Decimal, InvalidOperation
from fastapi.responses import PlainTextResponse
import app.admin_dashboard as legacy
from app.admin_dashboard import *  # noqa: F401,F403

router = APIRouter()


def _validate_product_form_payload(data: dict) -> str:
    sku = str(data.get("sku") or "").strip()
    name = str(data.get("name") or "").strip()
    if not sku:
        return "SKU é obrigatório."
    if not name:
        return "Nome do produto é obrigatório."
    for key, label, allow_blank, min_value in [
        ("default_unit_price", "Preço base", True, Decimal("0")),
        ("vat_rate", "IVA", True, Decimal("0")),
    ]:
        value = data.get(key)
        if allow_blank and (value is None or str(value).strip() == ""):
            continue
        try:
            decimal_value = Decimal(str(value).replace(",", ".").strip())
        except (InvalidOperation, ValueError):
            return f"{label} inválido."
        if decimal_value < min_value:
            return f"{label} não pode ser negativo."
    return ""


@router.get("/products", response_class=HTMLResponse)
@router.get("/produtos", response_class=HTMLResponse)
async def products_page(
    q: Optional[str] = None,
    category: Optional[str] = "all",
    active: Optional[str] = "true",
):
    products = list_products(q=q, category=category, active=("true" if active == "missing_jasmin" else active), limit=500)
    if active == "missing_jasmin":
        products = [p for p in products if not p.get("jasmin_sales_item")]
    categories = list_product_categories()

    category_options = '<option value="all">Todas</option>'
    for cat in categories:
        selected = "selected" if category == cat else ""
        category_options += f'<option value="{esc(cat)}" {selected}>{esc(cat)}</option>'

    active_options = ""
    for value, label in [("true", "Ativos"), ("missing_jasmin", "Ativos sem Artigo Jasmin"), ("false", "Inativos"), ("all", "Todos")]:
        selected = "selected" if (active or "true") == value else ""
        active_options += f'<option value="{esc(value)}" {selected}>{esc(label)}</option>'

    rows = ""
    for product in products:
        rows += f'''
        <tr>
          <td><code>{esc(product.get('sku') or '—')}</code></td>
          <td><code>{esc(product.get('jasmin_sales_item') or '—')}</code></td>
          <td><a class="cf-row-link" href="/products/{esc(product.get('id'))}">{esc(product.get('name') or 'Produto')}</a><div class="small text-secondary text-break">{esc(product.get('description') or '')}</div></td>
          <td>{esc(product.get('category') or '—')}</td>
          <td class="text-end fw-bold">{money_html(product.get('default_unit_price'))}</td>
          <td class="text-end">{esc(product.get('vat_rate') or '23')}%</td>
          <td>{product_status_badge(product.get('active'))}</td>
          <td class="text-end"><a class="btn btn-sm btn-outline-primary" href="/products/{esc(product.get('id'))}">Abrir</a></td>
        </tr>
        '''
    if not rows:
        rows = '<tr><td colspan="8" class="text-center text-secondary py-5">Sem produtos encontrados.</td></tr>'

    body = f'''
    <section class="cf-kpi-grid">
      {kpi_card('Produtos listados', len(products), '/products', 'catálogo', 'bi-box-seam')}
      {kpi_card('Ativos', sum(1 for p in products if p.get('active')), '/products?active=true', 'para orçamento', 'bi-check2-circle', 'cf-kpi-tone-green')}
      {kpi_card('Categorias', len(categories), '/products?category=Carregadores', 'organização', 'bi-tags')}
      {kpi_card('Novo produto', '+', '/products/new', 'adicionar', 'bi-plus-circle')}
    </section>

    <section class="card cf-card cf-filter-card">
      <form method="get" action="/products" class="row g-3 align-items-end">
        <div class="col-lg-5">
          <label class="form-label small fw-bold text-secondary">Procurar produto</label>
          <input class="form-control" type="search" name="q" value="{esc(q or '')}" placeholder="SKU, nome, categoria...">
        </div>
        <div class="col-lg-3">
          <label class="form-label small fw-bold text-secondary">Categoria</label>
          <select class="form-select" name="category">{category_options}</select>
        </div>
        <div class="col-lg-2">
          <label class="form-label small fw-bold text-secondary">Estado</label>
          <select class="form-select" name="active">{active_options}</select>
        </div>
        <div class="col-lg-2 d-flex gap-2">
          <button class="btn btn-primary flex-fill" type="submit">Filtrar</button>
          <a class="btn btn-outline-secondary" href="/products">Limpar</a>
        </div>
      </form>
    </section>

    <section class="card cf-card">
      <div class="card-body p-0">
        <div class="p-3 border-bottom d-flex flex-wrap justify-content-between align-items-center gap-2">
          <div>
            <h2 class="cf-section-title">Catálogo de produtos</h2>
            <div class="small text-secondary">Produtos e serviços usados nas oportunidades, orçamentos e encomendas.</div>
          </div>
          <div class="d-flex flex-wrap gap-2"><a class="btn btn-outline-primary btn-sm" href="/products/validate-jasmin">Validar artigos Jasmin</a><a class="btn btn-primary btn-sm" href="/products/new">+ Novo produto</a></div>
        </div>
        <div class="cf-table-wrap border-0 rounded-0">
          <table class="table cf-table">
            <thead><tr><th>SKU/Odoo</th><th>Jasmin</th><th>Produto</th><th>Categoria</th><th class="text-end">Preço</th><th class="text-end">IVA</th><th>Estado</th><th></th></tr></thead>
            <tbody>{rows}</tbody>
          </table>
        </div>
      </div>
    </section>
    '''
    return layout("Produtos", "Catálogo simples sem variantes, usado para propostas e encomendas", body, "products")


@router.get("/products/validate-jasmin", response_class=HTMLResponse)
async def products_validate_jasmin_page():
    products = list_products(active="true", limit=500)
    rows = ""
    checked = 0
    ok_count = 0
    missing_count = 0
    invalid_count = 0
    client = None
    if settings.jasmin_enabled:
        try:
            from app.jasmin_client import JasminClient
            client = JasminClient()
        except Exception as exc:
            rows += f'<tr><td colspan="5" class="text-danger">Erro de configuração Jasmin: {esc(exc)}</td></tr>'
    for product in products:
        jasmin_item = str(product.get("jasmin_sales_item") or "").strip()
        status = "Sem Artigo Jasmin"
        detail = ""
        chip = "cf-chip-orange"
        if not jasmin_item:
            missing_count += 1
        elif not client:
            status = "Não testado"
            detail = "Jasmin desativado ou configuração inválida"
            chip = "cf-chip-gray"
        else:
            checked += 1
            try:
                info = await client.get_sales_item(jasmin_item)
                if isinstance(info, dict) and info.get("itemKey"):
                    status = "OK"
                    detail = info.get("description") or info.get("itemKey") or ""
                    chip = "cf-chip-green"
                    ok_count += 1
                else:
                    status = "Resposta inesperada"
                    detail = str(info)[:180]
                    chip = "cf-chip-red"
                    invalid_count += 1
            except Exception as exc:
                status = "Não existe / erro"
                detail = str(exc)[:220]
                chip = "cf-chip-red"
                invalid_count += 1
        rows += f'''
        <tr>
          <td><code>{esc(product.get('sku') or '—')}</code></td>
          <td><code>{esc(jasmin_item or '—')}</code></td>
          <td><a class="cf-row-link" href="/products/{esc(product.get('id'))}">{esc(product.get('name') or 'Produto')}</a></td>
          <td><span class="cf-chip {chip}">{esc(status)}</span></td>
          <td class="small text-secondary text-break">{esc(detail)}</td>
        </tr>
        '''
    if not rows:
        rows = '<tr><td colspan="5" class="text-center text-secondary py-5">Sem produtos ativos.</td></tr>'
    body = f'''
    <a class="cf-row-link d-inline-flex mb-3" href="/products">← Voltar a produtos</a>
    <section class="cf-kpi-grid">
      {kpi_card('OK', ok_count, None, 'artigos válidos', 'bi-check2-circle', 'cf-kpi-tone-green')}
      {kpi_card('Sem artigo', missing_count, None, 'precisam mapeamento', 'bi-box-seam', 'cf-kpi-tone-orange')}
      {kpi_card('Inválidos/erro', invalid_count, None, 'corrigir antes de orçamentar', 'bi-exclamation-triangle', 'cf-kpi-tone-red')}
      {kpi_card('Testados', checked, None, 'consultas Jasmin', 'bi-patch-check')}
    </section>
    <section class="card cf-card"><div class="card-body p-0">
      <div class="p-3 border-bottom"><h2 class="cf-section-title">Validação de artigos Jasmin</h2><div class="small text-secondary">Confirma se products.jasmin_sales_item existe no Jasmin.</div></div>
      <div class="cf-table-wrap border-0 rounded-0"><table class="table cf-table"><thead><tr><th>SKU/Odoo</th><th>Artigo Jasmin</th><th>Produto</th><th>Estado</th><th>Detalhe</th></tr></thead><tbody>{rows}</tbody></table></div>
    </div></section>
    '''
    return layout("Validar artigos Jasmin", "Verificação de mapeamentos de produtos", body, "products")


@router.get("/products/new", response_class=HTMLResponse)
async def product_new_page():
    body = f'''
    <a class="cf-row-link d-inline-flex mb-3" href="/products">← Voltar a produtos</a>
    <section class="card cf-card"><div class="card-body p-4">
      <h2 class="cf-section-title mb-3">Novo produto</h2>
      {product_form_html({}, action="/products", submit_label="Criar produto")}
    </div></section>
    '''
    return layout("Novo produto", "Adicionar produto ou serviço ao catálogo", body, "products")


@router.post("/products")
async def product_create(request: Request):
    data = dict(await request.form())
    validation_error = _validate_product_form_payload(data)
    if validation_error:
        body = f'''
        <a class="cf-row-link d-inline-flex mb-3" href="/products">← Voltar a produtos</a>
        <section class="alert alert-danger">{esc(validation_error)}</section>
        <section class="card cf-card"><div class="card-body p-4">{product_form_html(data, action="/products", submit_label="Criar produto")}</div></section>
        '''
        return HTMLResponse(layout("Novo produto", "Corrige os campos e tenta novamente", body, "products"), status_code=422)
    try:
        product_id = create_product(data)
        return RedirectResponse(f"/products/{product_id}", status_code=303)
    except Exception as exc:
        body = f'''
        <a class="cf-row-link d-inline-flex mb-3" href="/products">← Voltar a produtos</a>
        <section class="alert alert-danger">Erro ao criar produto: {esc(exc)}</section>
        <section class="card cf-card"><div class="card-body p-4">{product_form_html(data, action="/products", submit_label="Criar produto")}</div></section>
        '''
        return HTMLResponse(layout("Novo produto", "Corrige os campos e tenta novamente", body, "products"), status_code=422)


@router.get("/products/{product_id}", response_class=HTMLResponse)
async def product_detail_page(product_id: str):
    if not is_uuid_text(product_id):
        return PlainTextResponse("Identificador de produto inválido.", status_code=422)
    product = get_product(product_id)
    if not product:
        return layout("Produto não encontrado", "Catálogo", '<section class="cf-empty">Produto não encontrado.</section>', "products")

    toggle_label = "Desativar" if product.get("active") else "Ativar"
    toggle_active = "false" if product.get("active") else "true"
    body = f'''
    <a class="cf-row-link d-inline-flex mb-3" href="/products">← Voltar a produtos</a>
    <div class="cf-two-col">
      <section class="card cf-card"><div class="card-body p-4">
        <div class="d-flex flex-wrap justify-content-between align-items-start gap-3 mb-3">
          <div>
            <span class="text-secondary small fw-bold text-uppercase">Produto</span>
            <h2 class="h3 fw-bold mb-1">{esc(product.get('name') or 'Produto')}</h2>
            <div class="small text-secondary">SKU/Odoo <code>{esc(product.get('sku') or '—')}</code> · Jasmin <code>{esc(product.get('jasmin_sales_item') or '—')}</code> · {esc(product.get('category') or 'Geral')}</div>
          </div>
          {product_status_badge(product.get('active'))}
        </div>
        {product_form_html(product, action=f"/products/{product_id}/update", submit_label="Guardar alterações")}
      </div></section>
      <aside class="cf-side">
        <section class="card cf-card"><div class="card-body p-3">
          <h2 class="cf-section-title mb-3">Resumo</h2>
          <div class="cf-soft-box mb-2"><div class="small text-secondary fw-bold">Preço base</div><strong>{money_html(product.get('default_unit_price'))}</strong></div>
          <div class="cf-soft-box mb-2"><div class="small text-secondary fw-bold">IVA</div><strong>{esc(product.get('vat_rate') or '23')}%</strong></div>
          <div class="cf-soft-box"><div class="small text-secondary fw-bold">Atualizado</div><strong>{esc(product.get('updated_at') or '—')}</strong></div>
        </div></section>
        <section class="card cf-card"><div class="card-body p-3">
          <h2 class="cf-section-title mb-3">Ações</h2>
          <form method="post" action="/products/{esc(product_id)}/toggle" class="d-grid">
            <input type="hidden" name="active" value="{esc(toggle_active)}">
            <button class="btn btn-outline-secondary" type="submit">{esc(toggle_label)} produto</button>
          </form>
        </div></section>
      </aside>
    </div>
    '''
    return layout(str(product.get("name") or "Produto"), "Editar produto do catálogo", body, "products")


@router.post("/products/{product_id}/update")
async def product_update(product_id: str, request: Request):
    if not is_uuid_text(product_id):
        return PlainTextResponse("Identificador de produto inválido.", status_code=422)
    data = dict(await request.form())
    validation_error = _validate_product_form_payload(data)
    if validation_error:
        product = get_product(product_id) or data
        body = f'''
        <a class="cf-row-link d-inline-flex mb-3" href="/products/{esc(product_id)}">← Voltar ao produto</a>
        <section class="alert alert-danger">{esc(validation_error)}</section>
        <section class="card cf-card"><div class="card-body p-4">{product_form_html(product, action=f"/products/{product_id}/update", submit_label="Guardar alterações")}</div></section>
        '''
        return HTMLResponse(layout("Editar produto", "Corrige os campos e tenta novamente", body, "products"), status_code=422)
    try:
        update_product(product_id, data)
        return RedirectResponse(f"/products/{product_id}", status_code=303)
    except Exception as exc:
        product = get_product(product_id) or data
        body = f'''
        <a class="cf-row-link d-inline-flex mb-3" href="/products/{esc(product_id)}">← Voltar ao produto</a>
        <section class="alert alert-danger">Erro ao guardar produto: {esc(exc)}</section>
        <section class="card cf-card"><div class="card-body p-4">{product_form_html(product, action=f"/products/{product_id}/update", submit_label="Guardar alterações")}</div></section>
        '''
        return HTMLResponse(layout("Editar produto", "Corrige os campos e tenta novamente", body, "products"), status_code=422)


@router.post("/products/{product_id}/toggle")
async def product_toggle(product_id: str, request: Request):
    if not is_uuid_text(product_id):
        return PlainTextResponse("Identificador de produto inválido.", status_code=422)
    data = dict(await request.form())
    ok = set_product_active(product_id, str(data.get("active") or "false").lower() == "true")
    if not ok:
        return PlainTextResponse("Produto não encontrado.", status_code=404)
    return RedirectResponse(f"/products/{product_id}", status_code=303)


@router.post("/opportunities/{opportunity_id}/items/add")
async def opportunity_item_add(opportunity_id: str, request: Request):
    if not is_uuid_text(opportunity_id):
        return PlainTextResponse("Identificador de oportunidade inválido.", status_code=422)
    data = dict(await request.form())
    try:
        add_opportunity_item(
            opportunity_id,
            product_id=data.get("product_id") or None,
            product_name=data.get("product_name") or None,
            jasmin_sales_item=data.get("jasmin_sales_item") or None,
            quantity=data.get("quantity") or "1",
            unit_price=data.get("unit_price") or None,
            discount_amount=data.get("discount_amount") or "0",
            status=data.get("status") or "INTERESTED",
        )
    except Exception as exc:
        print(f"ClientFlow add opportunity item failed: {exc}", flush=True)
        if is_htmx(request):
            return HTMLResponse(opportunity_products_panel_html(opportunity_id, error_notice=str(exc)), status_code=422)
        return PlainTextResponse(f"Dados inválidos ao adicionar item: {exc}", status_code=422)
    if is_htmx(request):
        return HTMLResponse(opportunity_products_panel_html(opportunity_id, notice="Produto adicionado à oportunidade."))
    return RedirectResponse(f"/opportunities/{opportunity_id}?notice=Produto%20adicionado%20%C3%A0%20oportunidade", status_code=303)


@router.post("/opportunities/{opportunity_id}/items/{item_id}/delete")
async def opportunity_item_delete(opportunity_id: str, item_id: str, request: Request):
    if not is_uuid_text(opportunity_id) or not is_uuid_text(item_id):
        return PlainTextResponse("Identificador inválido.", status_code=422)
    try:
        delete_opportunity_item(item_id)
    except Exception as exc:
        print(f"ClientFlow delete opportunity item failed: {exc}", flush=True)
        if is_htmx(request):
            return HTMLResponse(opportunity_products_panel_html(opportunity_id, error_notice=str(exc)), status_code=422)
        return PlainTextResponse(f"Dados inválidos ao adicionar item: {exc}", status_code=422)
    if is_htmx(request):
        return HTMLResponse(opportunity_products_panel_html(opportunity_id, notice="Produto removido."))
    return RedirectResponse(f"/opportunities/{opportunity_id}", status_code=303)


