import { Panel } from './Panel';
import { t } from '@/services/i18n';
import { escapeHtml, unsafeRawHtml } from '@/utils/sanitize';
import { getHydratedData } from '@/services/bootstrap';
import { createLazyClient, getRpcBaseUrl, rpcFetch } from '@/services/rpc-client';

import type { ListBigMacPricesResponse } from '@/generated/client/worldmonitor/economic/v1/service_client';
import { EconomicServiceClient } from '@/services/generated-rpc-clients';

const getEconomicClient = createLazyClient(() => new EconomicServiceClient(getRpcBaseUrl(), { fetch: rpcFetch }));

export class BigMacPanel extends Panel {
  constructor() {
    super({ id: 'bigmac', title: t('panels.bigmac'), infoTooltip: t('components.bigmac.infoTooltip') });
  }

  public async fetchData(): Promise<void> {
    try {
      const hydrated = getHydratedData('bigmac') as ListBigMacPricesResponse | undefined;
      if (hydrated?.countries?.length) {
        if (!this.element?.isConnected) return;
        this.renderIndex(hydrated);
        void getEconomicClient().listBigMacPrices({}).then(data => {
          if (!this.element?.isConnected || !data.countries?.length) return;
          this.renderIndex(data);
        }).catch(() => {});
        return;
      }
      const data = await getEconomicClient().listBigMacPrices({});
      if (!this.element?.isConnected) return;
      this.renderIndex(data);
    } catch (err) {
      if (this.isAbortError(err)) return;
      if (!this.element?.isConnected) return;
      this.showError(t('common.failedMarketData'), () => void this.fetchData());
    }
  }

  private renderIndex(data: ListBigMacPricesResponse): void {
    if (!data.countries?.length) {
      this.showError(t('common.failedMarketData'), () => void this.fetchData());
      return;
    }

    const sorted = [...data.countries]
      .filter((c): c is typeof c & { usdPrice: number } => c.usdPrice != null && c.usdPrice > 0)
      .sort((a, b) => b.usdPrice - a.usdPrice);

    const maxCode = sorted[0]?.code;
    const minCode = sorted[sorted.length - 1]?.code;

    const showWow = data.wowAvailable && data.wowAvgPct !== undefined;
    const wowHeader = showWow ? `<th class="gb-cell">${t('panels.bigmacWow')}</th>` : '';

    const rows = sorted.map(c => {
      const cls = c.code === minCode ? 'gb-cheapest' : c.code === maxCode ? 'gb-priciest' : '';
      let wowCell = '';
      if (showWow) {
        const pct = c.wowPct ?? null;
        if (pct == null) {
          wowCell = `<td class="gb-cell gb-na">—</td>`;
        } else {
          const sign = pct >= 0 ? '▲' : '▼';
          const wowCls = pct >= 0 ? 'bm-wow-up' : 'bm-wow-down';
          wowCell = `<td class="gb-cell ${wowCls}">${sign}${Math.abs(pct).toFixed(1)}%</td>`;
        }
      }
      return `<tr>
        <td class="gb-item-name">${escapeHtml(c.flag)} ${escapeHtml(c.name)}</td>
        <td class="gb-cell ${cls}">$${c.usdPrice.toFixed(2)}</td>
        ${wowCell}
      </tr>`;
    }).join('');

    let wowSummary = '';
    if (showWow) {
      const avg = data.wowAvgPct;
      const sign = avg >= 0 ? '▲' : '▼';
      const cls = avg >= 0 ? 'bm-wow-up' : 'bm-wow-down';
      wowSummary = `<div class="bm-wow-summary">Global avg: <span class="${cls}">${sign}${Math.abs(avg).toFixed(1)}% ${t('panels.bigmacWow')}</span></div>`;
    }

    const updatedAt = data.fetchedAt ? new Date(data.fetchedAt).toLocaleDateString() : '';

    const html = `
      <div class="gb-wrapper">
        ${wowSummary}
        <div class="gb-scroll">
          <table class="gb-table">
            <thead><tr>
              <th class="gb-item-col">${t('panels.bigmacCountry')}</th>
              <th class="gb-cell">USD</th>
              ${wowHeader}
            </tr></thead>
            <tbody>${rows}</tbody>
          </table>
        </div>
        ${updatedAt ? `<div class="gb-updated">${t('components.status.updatedAt', { time: updatedAt })}</div>` : ''}
      </div>
    `;

    this.setSafeContent(unsafeRawHtml(html, 'legacy Panel.setContent() migration'));
  }
}
