import { CommonModule } from '@angular/common';
import { Component, computed, inject, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { CatalogQuery, InvimaService } from '../../core/services/invima.service';
import {
  InvimaCatalogItem,
  InvimaCategory,
  InvimaDataset,
  InvimaFilterOption
} from '../../core/models';

@Component({
  selector: 'app-catalog-page',
  standalone: true,
  imports: [CommonModule, FormsModule],
  template: `
    <section class="catalog-page">
      <header class="top card">
        <div>
          <p class="eyebrow">Modulo principal</p>
          <h2>Catalogo INVIMA API</h2>
          <p class="sub">Consulta optimizada con busqueda inteligente y categorias unificadas.</p>
        </div>

        <div class="top-actions">
          <div class="top-actions-row">
            <button type="button" class="ghost" (click)="download('csv')" [disabled]="loading() || !!exporting()">
              {{ exporting() === 'csv' ? 'Descargando CSV...' : 'Descargar CSV' }}
            </button>
            <button type="button" class="ghost" (click)="download('xlsx')" [disabled]="loading() || !!exporting()">
              {{ exporting() === 'xlsx' ? 'Descargando Excel...' : 'Descargar Excel' }}
            </button>
          </div>
          <small class="export-msg ok" *ngIf="exportMessage() && !exportError()">{{ exportMessage() }}</small>
          <small class="export-msg error" *ngIf="exportError()">{{ exportError() }}</small>
        </div>
      </header>

      <section class="quick-stats">
        <span class="pill">Categorias: {{ categories().length }}</span>
        <span class="pill">Datasets: {{ datasets().length }}</span>
        <span class="pill">Seleccionadas: {{ selectedCategories().length }}</span>
        <span class="pill">Total resultados: {{ total() }}</span>
      </section>

      <form class="search card" (ngSubmit)="applyFilters()">
        <label>
          Busqueda
          <input
            type="text"
            name="query"
            [(ngModel)]="qText"
            placeholder="Ej: marcapasos, vacuna, vigente, titular, principio activo"
          />
        </label>

        <div class="search-actions">
          <button type="submit" [disabled]="loading()">Buscar</button>
          <button type="button" class="ghost" (click)="clearFilters()" [disabled]="loading()">Limpiar</button>
        </div>
      </form>

      <section class="filters card">
        <label>
          Estado
          <select [(ngModel)]="estado" [ngModelOptions]="{ standalone: true }">
            <option value="">Todos</option>
            <option *ngFor="let item of estados()" [value]="item.value">{{ item.value }} ({{ item.total }})</option>
          </select>
        </label>

        <label>
          Modalidad
          <select [(ngModel)]="modalidad" [ngModelOptions]="{ standalone: true }">
            <option value="">Todas</option>
            <option *ngFor="let item of modalidades()" [value]="item.value">{{ item.value }} ({{ item.total }})</option>
          </select>
        </label>

        <label>
          Grupo
          <select [(ngModel)]="grupo" [ngModelOptions]="{ standalone: true }">
            <option value="">Todos</option>
            <option *ngFor="let item of grupos()" [value]="item.value">{{ item.value }} ({{ item.total }})</option>
          </select>
        </label>

        <label>
          Venc. desde
          <input type="date" [(ngModel)]="fechaVencDesde" [ngModelOptions]="{ standalone: true }" />
        </label>

        <label>
          Venc. hasta
          <input type="date" [(ngModel)]="fechaVencHasta" [ngModelOptions]="{ standalone: true }" />
        </label>

        <label>
          Exp. desde
          <input type="date" [(ngModel)]="fechaExpDesde" [ngModelOptions]="{ standalone: true }" />
        </label>

        <label>
          Exp. hasta
          <input type="date" [(ngModel)]="fechaExpHasta" [ngModelOptions]="{ standalone: true }" />
        </label>

        <label class="switch">
          <input type="checkbox" [(ngModel)]="onlyVigentes" [ngModelOptions]="{ standalone: true }" />
          Solo vigentes
        </label>

        <button type="button" class="apply" (click)="applyFilters()" [disabled]="loading()">Aplicar filtros</button>
      </section>

      <section class="selector card">
        <header>
          <h3>Categorias</h3>
          <small>{{ selectedCategories().length }} seleccionadas</small>
        </header>

        <div class="grid">
          <label class="chip" *ngFor="let item of categories()">
            <input
              type="checkbox"
              [checked]="isCategorySelected(item)"
              (change)="toggleCategory(item, $any($event.target).checked)"
            />
            <span>{{ item.categoria }}</span>
            <small>{{ item.total }}</small>
          </label>
        </div>
      </section>

      <section class="selector card">
        <header>
          <h3>Datasets</h3>
          <small>{{ selectedDatasets().length }} seleccionados</small>
        </header>

        <div class="grid">
          <label class="chip" *ngFor="let item of datasets()">
            <input
              type="checkbox"
              [checked]="isDatasetSelected(item)"
              (change)="toggleDataset(item, $any($event.target).checked)"
            />
            <span>{{ item.name }}</span>
            <small>{{ item.key }}</small>
          </label>
        </div>
      </section>

      <section class="results card">
        <header class="table-head">
          <strong>Total encontrado: {{ total() }}</strong>

          <div class="pager">
            <label>
              Filas
              <select [ngModel]="limit()" (ngModelChange)="changeLimit($event)">
                <option [ngValue]="25">25</option>
                <option [ngValue]="50">50</option>
                <option [ngValue]="100">100</option>
              </select>
            </label>

            <button type="button" class="ghost" (click)="prevPage()" [disabled]="offset() === 0 || loading()">
              Anterior
            </button>
            <span>Pagina {{ page() }}</span>
            <button type="button" class="ghost" (click)="nextPage()" [disabled]="!hasMore() || loading()">
              Siguiente
            </button>
          </div>
        </header>

        <div class="state" *ngIf="loading()">Consultando catalogo...</div>
        <div class="state error" *ngIf="error()">{{ error() }}</div>
        <div class="state" *ngIf="!loading() && !error() && items().length === 0">
          No hay resultados con los filtros actuales.
        </div>

        <div class="table-wrap" *ngIf="!loading() && !error() && items().length">
          <table>
            <thead>
              <tr>
                <th>Categoria</th>
                <th>Registro</th>
                <th>Producto</th>
                <th>Estado</th>
                <th>Vencimiento</th>
                <th>Titular</th>
                <th>Dataset</th>
              </tr>
            </thead>
            <tbody>
              <tr *ngFor="let item of items()">
                <td>
                  <div class="stack">
                    <strong>{{ item.categoria_canonica || '--' }}</strong>
                    <small>{{ item.categoria_linea || '--' }}</small>
                  </div>
                </td>

                <td>
                  <div class="stack mono">
                    <span>{{ item.registro_sanitario || '--' }}</span>
                    <small>Exp: {{ item.expediente || '--' }}</small>
                  </div>
                </td>

                <td>
                  <div class="stack">
                    <strong>{{ item.producto || '--' }}</strong>
                    <small>{{ item.marca || '--' }}</small>
                    <small>{{ item.grupo || '--' }}</small>
                  </div>
                </td>

                <td>
                  <span class="badge" [class.ok]="isVigente(item)" [class.warn]="isVencido(item)">
                    {{ item.estado_registro || item.vigencia || '--' }}
                  </span>
                </td>

                <td>{{ formatDate(item.fecha_vencimiento) }}</td>

                <td>
                  <div class="stack">
                    <strong>{{ item.titular || '--' }}</strong>
                    <small>{{ item.ciudad_titular || '--' }} · {{ item.pais_titular || '--' }}</small>
                  </div>
                </td>

                <td>
                  <div class="stack">
                    <strong>{{ item.source_dataset_name }}</strong>
                    <small class="mono">{{ item.source_dataset_key }}</small>
                  </div>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </section>
    </section>
  `,
  styles: `
    .catalog-page {
      display: grid;
      gap: 14px;
    }

    .card {
      border-radius: 20px;
      border: 1px solid var(--color-border);
      background: var(--color-card);
      box-shadow: var(--shadow-soft);
      backdrop-filter: blur(3px);
    }

    .top {
      padding: 16px 18px;
      display: flex;
      justify-content: space-between;
      gap: 12px;
      align-items: flex-start;
      flex-wrap: wrap;
    }

    .eyebrow {
      margin: 0;
      font-size: 0.78rem;
      font-family: var(--font-display);
      color: var(--color-primary);
      font-weight: 700;
      letter-spacing: 0.03em;
    }

    h2 {
      margin: 8px 0 0;
      font-family: var(--font-display);
      color: var(--color-ink);
      font-size: 1.55rem;
    }

    .sub {
      margin: 6px 0 0;
      color: var(--color-muted);
      font-size: 0.92rem;
    }

    .top-actions {
      display: grid;
      gap: 6px;
      justify-items: end;
      align-content: start;
    }

    .top-actions-row {
      display: flex;
      gap: 8px;
      align-items: center;
    }

    .export-msg {
      font-size: 0.78rem;
      font-weight: 700;
    }

    .export-msg.ok {
      color: #0f7470;
    }

    .export-msg.error {
      color: #b71717;
    }

    .quick-stats {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
    }

    .pill {
      border-radius: 999px;
      border: 1px solid rgba(32, 178, 170, 0.22);
      background: rgba(255, 255, 255, 0.66);
      color: #334961;
      font-size: 0.8rem;
      font-weight: 700;
      padding: 7px 12px;
    }

    .search {
      padding: 14px 16px;
      display: grid;
      grid-template-columns: minmax(0, 1fr) auto;
      gap: 10px;
      align-items: end;
    }

    .search label,
    .filters label {
      display: grid;
      gap: 6px;
      color: #344b62;
      font-size: 0.84rem;
      font-weight: 700;
    }

    .search input,
    .filters input,
    .filters select,
    .pager select {
      border: 1px solid rgba(139, 148, 162, 0.5);
      border-radius: var(--radius-sm);
      background: rgba(255, 255, 255, 0.86);
      color: var(--color-ink);
      padding: 10px 12px;
      font-size: 0.95rem;
      outline: none;
      transition: border-color 0.14s ease, box-shadow 0.14s ease;
    }

    .search input:focus-visible,
    .filters input:focus-visible,
    .filters select:focus-visible,
    .pager select:focus-visible {
      border-color: rgba(32, 178, 170, 0.45);
      box-shadow: 0 0 0 3px rgba(32, 178, 170, 0.12);
    }

    .search-actions {
      display: flex;
      gap: 8px;
    }

    button {
      border-radius: 12px;
      border: 0;
      padding: 10px 14px;
      font-size: 0.9rem;
      font-weight: 700;
      cursor: pointer;
      transition: 0.16s ease;
    }

    button:disabled {
      opacity: 0.72;
      cursor: not-allowed;
    }

    button:not(.ghost) {
      background: linear-gradient(90deg, var(--color-primary), var(--color-primary-strong));
      color: #fff;
      box-shadow: 0 10px 20px rgba(32, 178, 170, 0.26);
    }

    button.ghost {
      background: #fff;
      border: 1px solid rgba(32, 178, 170, 0.26);
      color: var(--color-primary-strong);
    }

    .filters {
      padding: 14px;
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
      gap: 10px;
      align-items: end;
    }

    .switch {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding-bottom: 9px;
      font-size: 0.86rem;
      color: #30485f;
    }

    .switch input {
      width: 16px;
      height: 16px;
      margin: 0;
      padding: 0;
    }

    .apply {
      align-self: end;
      height: 44px;
    }

    .selector {
      padding: 14px;
    }

    .selector header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      gap: 10px;
      margin-bottom: 10px;
    }

    .selector h3 {
      margin: 0;
      font-family: var(--font-display);
      font-size: 1rem;
      color: var(--color-ink);
    }

    .selector small {
      color: #5f7189;
      font-size: 0.8rem;
      font-weight: 600;
    }

    .grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
      gap: 8px;
    }

    .chip {
      border: 1px solid rgba(160, 168, 179, 0.52);
      border-radius: 12px;
      background: rgba(255, 255, 255, 0.72);
      padding: 8px 9px;
      display: grid;
      grid-template-columns: auto 1fr auto;
      gap: 8px;
      align-items: center;
    }

    .chip span {
      font-size: 0.86rem;
      color: #1f3448;
      line-height: 1.3;
    }

    .chip small {
      color: #647790;
      font-size: 0.76rem;
    }

    .results {
      overflow: hidden;
    }

    .table-head {
      padding: 12px 14px;
      border-bottom: 1px solid rgba(168, 176, 188, 0.44);
      display: flex;
      justify-content: space-between;
      align-items: center;
      gap: 10px;
      flex-wrap: wrap;
    }

    .table-head strong {
      color: #1f3245;
    }

    .pager {
      display: flex;
      gap: 8px;
      align-items: center;
      color: #516881;
      font-size: 0.86rem;
    }

    .pager label {
      display: inline-flex;
      align-items: center;
      gap: 6px;
    }

    .state {
      padding: 14px;
      color: #4d5f79;
      font-size: 0.92rem;
    }

    .state.error {
      color: #b71717;
    }

    .table-wrap {
      overflow: auto;
    }

    table {
      width: 100%;
      border-collapse: collapse;
      min-width: 1080px;
    }

    thead {
      background: rgba(247, 245, 246, 0.95);
    }

    th,
    td {
      text-align: left;
      padding: 10px 12px;
      border-bottom: 1px solid rgba(180, 187, 197, 0.45);
      font-size: 0.84rem;
      vertical-align: top;
    }

    th {
      text-transform: uppercase;
      letter-spacing: 0.05em;
      color: #61738d;
      font-size: 0.73rem;
      font-family: var(--font-display);
      font-weight: 600;
    }

    .stack {
      display: grid;
      gap: 2px;
    }

    .stack strong {
      color: #1e3449;
      font-size: 0.88rem;
      line-height: 1.35;
    }

    .stack small {
      color: #61758f;
      font-size: 0.76rem;
      line-height: 1.3;
    }

    .mono {
      font-family: 'Consolas', 'Courier New', monospace;
    }

    .badge {
      display: inline-flex;
      align-items: center;
      border-radius: 999px;
      padding: 4px 8px;
      font-size: 0.72rem;
      text-transform: uppercase;
      letter-spacing: 0.03em;
      background: rgba(91, 109, 130, 0.15);
      color: #243a50;
    }

    .badge.ok {
      background: rgba(5, 150, 105, 0.14);
      color: #057857;
    }

    .badge.warn {
      background: rgba(185, 28, 28, 0.14);
      color: #b91c1c;
    }

    @media (max-width: 900px) {
      .search {
        grid-template-columns: 1fr;
      }

      .search-actions {
        justify-content: flex-start;
      }
    }
  `
})
export class CatalogPageComponent {
  private readonly invima = inject(InvimaService);

  readonly loading = signal(false);
  readonly error = signal('');
  readonly exporting = signal<'csv' | 'xlsx' | null>(null);
  readonly exportMessage = signal('');
  readonly exportError = signal('');
  readonly items = signal<InvimaCatalogItem[]>([]);
  readonly total = signal(0);

  readonly categories = signal<InvimaCategory[]>([]);
  readonly datasets = signal<InvimaDataset[]>([]);
  readonly estados = signal<InvimaFilterOption[]>([]);
  readonly modalidades = signal<InvimaFilterOption[]>([]);
  readonly grupos = signal<InvimaFilterOption[]>([]);

  readonly selectedCategories = signal<string[]>([]);
  readonly selectedDatasets = signal<string[]>([]);

  readonly limit = signal(25);
  readonly offset = signal(0);
  readonly page = computed(() => Math.floor(this.offset() / this.limit()) + 1);
  readonly hasMore = computed(() => this.offset() + this.limit() < this.total());

  qText = '';
  estado = '';
  modalidad = '';
  grupo = '';
  fechaVencDesde = '';
  fechaVencHasta = '';
  fechaExpDesde = '';
  fechaExpHasta = '';
  onlyVigentes = false;

  constructor() {
    this.loadMetadata();
    this.loadData();
  }

  private buildQuery(): CatalogQuery {
    return {
      q: this.qText.trim() || undefined,
      categorias: this.selectedCategories().length ? this.selectedCategories() : undefined,
      datasets: this.selectedDatasets().length ? this.selectedDatasets() : undefined,
      estados: this.estado ? [this.estado] : undefined,
      modalidades: this.modalidad ? [this.modalidad] : undefined,
      grupos: this.grupo ? [this.grupo] : undefined,
      fechaVencDesde: this.fechaVencDesde || undefined,
      fechaVencHasta: this.fechaVencHasta || undefined,
      fechaExpDesde: this.fechaExpDesde || undefined,
      fechaExpHasta: this.fechaExpHasta || undefined,
      onlyVigentes: this.onlyVigentes || undefined,
      limit: this.limit(),
      offset: this.offset()
    };
  }

  private loadMetadata() {
    this.invima.getCategories().subscribe({
      next: (response) => this.categories.set(response.items || []),
      error: () => this.categories.set([])
    });

    this.invima.getDatasets().subscribe({
      next: (response) => this.datasets.set(response.items || []),
      error: () => this.datasets.set([])
    });

    this.invima.getFilterOptions().subscribe({
      next: (response) => {
        this.estados.set(response.estados || []);
        this.modalidades.set(response.modalidades || []);
        this.grupos.set(response.grupos || []);
      },
      error: () => {
        this.estados.set([]);
        this.modalidades.set([]);
        this.grupos.set([]);
      }
    });
  }

  private loadData() {
    this.loading.set(true);
    this.error.set('');

    this.invima.searchCatalog(this.buildQuery()).subscribe({
      next: (response) => {
        this.items.set(response.items || []);
        this.total.set(response.total || 0);
        this.loading.set(false);
      },
      error: () => {
        this.error.set('No se pudo consultar el catalogo. Revisa conexion del backend.');
        this.loading.set(false);
      }
    });
  }

  applyFilters() {
    this.offset.set(0);
    this.loadData();
  }

  clearFilters() {
    this.qText = '';
    this.estado = '';
    this.modalidad = '';
    this.grupo = '';
    this.fechaVencDesde = '';
    this.fechaVencHasta = '';
    this.fechaExpDesde = '';
    this.fechaExpHasta = '';
    this.onlyVigentes = false;
    this.selectedCategories.set([]);
    this.selectedDatasets.set([]);
    this.offset.set(0);
    this.loadData();
  }

  toggleCategory(item: InvimaCategory, checked: boolean) {
    const current = this.selectedCategories();
    if (checked) {
      if (current.includes(item.slug)) return;
      this.selectedCategories.set([...current, item.slug]);
      return;
    }
    this.selectedCategories.set(current.filter((slug) => slug !== item.slug));
  }

  isCategorySelected(item: InvimaCategory) {
    return this.selectedCategories().includes(item.slug);
  }

  toggleDataset(item: InvimaDataset, checked: boolean) {
    const current = this.selectedDatasets();
    if (checked) {
      if (current.includes(item.key)) return;
      this.selectedDatasets.set([...current, item.key]);
      return;
    }
    this.selectedDatasets.set(current.filter((key) => key !== item.key));
  }

  isDatasetSelected(item: InvimaDataset) {
    return this.selectedDatasets().includes(item.key);
  }

  changeLimit(next: number) {
    const parsed = Number(next) || 25;
    this.limit.set(parsed);
    this.offset.set(0);
    this.loadData();
  }

  nextPage() {
    if (!this.hasMore()) return;
    this.offset.set(this.offset() + this.limit());
    this.loadData();
  }

  prevPage() {
    if (this.offset() === 0) return;
    this.offset.set(Math.max(0, this.offset() - this.limit()));
    this.loadData();
  }

  download(format: 'csv' | 'xlsx') {
    if (this.exporting()) return;

    this.exporting.set(format);
    this.exportError.set('');
    this.exportMessage.set('');

    this.invima.exportCatalog(this.buildQuery(), format).subscribe({
      next: (file) => {
        const blob = file.blob.type ? file.blob : new Blob([file.blob], { type: file.contentType });
        const url = window.URL.createObjectURL(blob);
        const anchor = document.createElement('a');
        anchor.href = url;
        anchor.download = file.filename;
        anchor.style.display = 'none';
        document.body.appendChild(anchor);
        anchor.click();
        anchor.remove();
        window.URL.revokeObjectURL(url);

        this.exporting.set(null);
        this.exportMessage.set(`Archivo ${format.toUpperCase()} descargado correctamente.`);
      },
      error: (error) => {
        this.exporting.set(null);
        if (error?.status === 401) {
          this.exportError.set('Sesion expirada. Inicia sesion nuevamente.');
          return;
        }
        this.exportError.set('No fue posible descargar el archivo en este momento.');
      }
    });
  }

  formatDate(value: string | undefined) {
    if (!value) return '--';
    const date = new Date(value);
    if (Number.isNaN(date.getTime())) return value;
    return date.toISOString().slice(0, 10);
  }

  isVigente(item: InvimaCatalogItem) {
    const status = (item.estado_registro || item.vigencia || '').toLowerCase();
    return status.includes('vigente') && !status.includes('no vigente');
  }

  isVencido(item: InvimaCatalogItem) {
    const status = (item.estado_registro || item.vigencia || '').toLowerCase();
    return status.includes('vencido');
  }
}

