import { useRef, useState } from 'react';
import { Flame, ChevronDown } from 'lucide-react';
import { cn } from '@/lib/utils';
import { MeterBar } from '@/components/MeterBar';
import { AmpOperate, AmpPower, AmpPowerLevel, AmpFanMode, FlexAmpOperate } from '../../wailsjs/go/main/App';

// AmpCard renders the amplifier card exactly like the one in the FlexRadio panel,
// so Station Control (and anywhere else that needs it) shows the SAME card instead
// of a stripped-down variant. It handles all three amp families:
//   • SPE Expert / ACOM — driven by OpsLog's own serial/TCP link (amp.spe/amp.acom)
//   • PowerGenius XL     — OPERATE + meters come from the Flex (which reports the
//                          amp), fan mode from the direct GSCP link (amp.pgxl)
// Controls use the multi-amp API (AmpOperate/AmpPower/… by amp id) so several amps
// can each get their own card.

function Card({ icon: Icon, title, accent, children, ckey }: { icon: any; title: string; accent?: string; children: React.ReactNode; ckey?: string }) {
  // Collapsible with persisted state — same behaviour as the FlexRadio panel's Card.
  const storeKey = 'opslog.cardOpen.' + (ckey || title);
  const [open, setOpen] = useState(() => localStorage.getItem(storeKey) !== '0');
  const toggle = () => setOpen((o) => { const n = !o; localStorage.setItem(storeKey, n ? '1' : '0'); return n; });
  return (
    <div className="rounded-xl border border-border bg-card shadow-sm overflow-hidden">
      <button type="button" onClick={toggle}
        className={cn('w-full flex items-center gap-2 px-3 py-2 bg-muted/30 hover:bg-muted/50 transition-colors text-left', open && 'border-b border-border/60')}>
        <Icon className="size-4" style={{ color: accent ?? 'var(--primary)' }} />
        <span className="text-xs font-bold uppercase tracking-wider text-foreground/80">{title}</span>
        <ChevronDown className={cn('ml-auto size-4 text-muted-foreground transition-transform', !open && '-rotate-90')} />
      </button>
      {open && <div className="p-3 space-y-3">{children}</div>}
    </div>
  );
}

// speMaxW / powerLevelLabel — same helpers the Flex panel uses.
function speMaxW(model?: string): number {
  const m = (model || '').toUpperCase();
  if (m.includes('20K') || m.includes('2K')) return 2000;
  if (m.includes('15K')) return 1500;
  return 1300;
}
function powerLevelLabel(pl?: string): string {
  switch ((pl || '').trim().toUpperCase()) {
    case 'L': return 'Low';
    case 'M': return 'Mid';
    case 'H': return 'High';
    default: return pl || '';
  }
}

type Amp = { id: string; name: string; type?: string; spe?: any; acom?: any; kpa?: any; pgxl?: any };

export function AmpCard({ amp, flex, t }: { amp: Amp; flex: any; t: (k: string, v?: any) => string }) {
  // Peak-hold so the jittery VITA-49 meters read steadily (own ref per card).
  // One second: the same window as the docked widget, so the two never show
  // different figures for the same amplifier, and neither trails the end of a
  // transmission long enough to look like lag.
  const peak = useRef<Record<string, { v: number; t: number }>>({});
  const peakHold = (key: string, val: number) => {
    const now = Date.now();
    const p = peak.current[key];
    if (!p || val >= p.v || now - p.t > 1000) { peak.current[key] = { v: val, t: now }; return val; }
    return p.v;
  };

  const isSPE = !!amp.spe;
  const isACOM = !!amp.acom;
  const isKPA = !!amp.kpa;

  if (isSPE) {
    const spe = amp.spe;
    return (
      <Card icon={Flame} ckey="amplifier" title={`${t('flxp.amplifier')} · ${amp.name || `SPE${spe.model ? ' ' + spe.model : ''}`}`} accent="#ea580c">
        <div className="flex items-center gap-3 flex-wrap">
          <button type="button" disabled={!spe.connected}
            onClick={() => AmpOperate(amp.id, !spe.operate).catch(() => {})}
            className={cn('px-4 py-2 rounded-lg text-sm font-extrabold tracking-wide border-2 transition-all disabled:opacity-30',
              spe.operate ? 'bg-warning text-warning-foreground border-warning shadow-[0_0_14px] shadow-warning/50' : 'bg-card text-warning border-warning hover:bg-warning-muted')}>
            {spe.operate ? 'OPERATE' : 'STANDBY'}
          </button>
          {/* Power ON pulses RTS then DTR — it must stay clickable while the amp
              is off (no status = not "connected"), and serial only. */}
          <div className="inline-flex rounded-lg overflow-hidden border-2 border-success/70">
            <button type="button" disabled={!(spe.connected || spe.transport === 'serial')}
              onClick={() => AmpPower(amp.id, true).catch(() => {})}
              title={spe.transport === 'serial' ? 'Power on (RTS then DTR pulse)' : 'Power-on needs the serial RTS/DTR lines — not available over a network bridge'}
              className="px-3 py-2 text-sm font-bold bg-card text-success hover:bg-success/15 disabled:opacity-30">ON</button>
            <button type="button" disabled={!spe.connected}
              onClick={() => AmpPower(amp.id, false).catch(() => {})}
              className="px-3 py-2 text-sm font-bold bg-card text-danger border-l-2 border-success/70 hover:bg-danger/15 disabled:opacity-30">OFF</button>
          </div>
          <div className="inline-flex rounded-lg overflow-hidden border border-border">
            {(['L', 'M', 'H'] as const).map((lvl, i) => {
              const active = (spe.power_level || '').trim().toUpperCase() === lvl;
              return (
                <button key={lvl} type="button" disabled={!spe.connected}
                  onClick={() => AmpPowerLevel(amp.id, lvl).catch(() => {})}
                  className={cn('px-3 py-2 text-sm font-bold disabled:opacity-30', i > 0 && 'border-l border-border',
                    active ? 'bg-primary text-primary-foreground' : 'bg-card text-muted-foreground hover:bg-muted')}>
                  {powerLevelLabel(lvl)}
                </button>
              );
            })}
          </div>
          <span className={cn('inline-flex items-center gap-1.5 text-sm', spe.connected ? 'text-muted-foreground' : 'text-danger')}>
            <span className={cn('size-2 rounded-full', spe.connected ? 'bg-success' : 'bg-danger')} />
            {spe.connected ? (spe.tx ? 'TX' : 'RX') : t('flxp.speOffline')}
          </span>
          {spe.connected && (
            <span className="text-sm font-mono text-muted-foreground tabular-nums">
              {spe.band ? `${spe.band} · ` : ''}{spe.output_w}W · SWR {Number(spe.swr_ant ?? 0).toFixed(1)} · {spe.temp_c}°C · {powerLevelLabel(spe.power_level)}
            </span>
          )}
          <div className="flex-1" />
          {(spe.warnings || spe.alarms) && (
            <span className="px-2 py-1 rounded bg-danger-muted text-danger-muted-foreground text-xs font-bold">⚠ {spe.warnings} {spe.alarms}</span>
          )}
        </div>
        {spe.connected && (
          <MeterBar label={t('flxp.outputPower')} value={Number(spe.output_w) || 0} unit="W"
            lo={0} hi={speMaxW(spe.model)}
            display={`${Number(spe.output_w) || 0} W`}
            segColor={(f) => (f > 0.9 ? '#dc2626' : f > 0.75 ? '#f59e0b' : '#ea580c')} />
        )}
      </Card>
    );
  }

  if (isACOM) {
    const acom = amp.acom;
    return (
      <Card icon={Flame} ckey="amplifier" title={`${t('flxp.amplifier')} · ${amp.name || `Acom${acom.model ? ' ' + acom.model : ''}`}`} accent="#ea580c">
        <div className="flex items-center gap-3 flex-wrap">
          <button type="button" disabled={!acom.connected}
            onClick={() => AmpOperate(amp.id, !acom.operate).catch(() => {})}
            className={cn('px-4 py-2 rounded-lg text-sm font-extrabold tracking-wide border-2 transition-all disabled:opacity-30',
              acom.operate ? 'bg-warning text-warning-foreground border-warning shadow-[0_0_14px] shadow-warning/50' : 'bg-card text-warning border-warning hover:bg-warning-muted')}>
            {acom.operate ? 'OPERATE' : 'STANDBY'}
          </button>
          <div className="inline-flex rounded-lg overflow-hidden border-2 border-success/70">
            <button type="button" disabled={!(acom.port_open && acom.transport === 'serial')}
              onClick={() => AmpPower(amp.id, true).catch(() => {})}
              title={acom.transport === 'serial' ? 'Power on (DTR/RTS pulse — needs the power-on pins wired)' : 'Power-on needs the serial DTR/RTS lines — not available over a network bridge'}
              className="px-3 py-2 text-sm font-bold bg-card text-success hover:bg-success/15 disabled:opacity-30">ON</button>
            <button type="button" disabled={!acom.connected}
              onClick={() => AmpPower(amp.id, false).catch(() => {})}
              className="px-3 py-2 text-sm font-bold bg-card text-danger border-l-2 border-success/70 hover:bg-danger/15 disabled:opacity-30">OFF</button>
          </div>
          <span className={cn('inline-flex items-center gap-1.5 text-sm', acom.connected ? 'text-muted-foreground' : 'text-danger')}>
            <span className={cn('size-2 rounded-full', acom.connected ? 'bg-success' : 'bg-danger')} />
            {acom.connected ? acom.state : t('flxp.acomOffline')}
          </span>
          {acom.connected && (
            <span className="text-sm font-mono text-muted-foreground tabular-nums">
              {acom.band ? `${acom.band} · ` : ''}{acom.fwd_w}W · SWR {Number(acom.swr ?? 0).toFixed(1)} · {acom.temp_c}°C · Fan {acom.fan}
            </span>
          )}
          <div className="flex-1" />
          {acom.err_text && (
            <span className="px-2 py-1 rounded bg-danger-muted text-danger-muted-foreground text-xs font-bold">⚠ {acom.err_text}</span>
          )}
        </div>
        {acom.connected && (
          <MeterBar label={t('flxp.outputPower')} value={Number(acom.fwd_w) || 0} unit="W"
            lo={0} hi={Number(acom.max_w) || 800}
            display={`${Number(acom.fwd_w) || 0} W`}
            segColor={(f) => (f > 0.9 ? '#dc2626' : f > 0.75 ? '#f59e0b' : '#ea580c')} />
        )}
      </Card>
    );
  }

  if (isKPA) {
    const kpa = amp.kpa;
    return (
      <Card icon={Flame} ckey="amplifier" title={`${t('flxp.amplifier')} · ${amp.name || kpa.model || 'Elecraft'}`} accent="#ea580c">
        <div className="flex items-center gap-3 flex-wrap">
          <button type="button" disabled={!kpa.connected}
            onClick={() => AmpOperate(amp.id, !kpa.operate).catch(() => {})}
            title={kpa.fault_text ? t('flxp.kpaClearsFault') : undefined}
            className={cn('px-4 py-2 rounded-lg text-sm font-extrabold tracking-wide border-2 transition-all disabled:opacity-30',
              kpa.operate ? 'bg-warning text-warning-foreground border-warning shadow-[0_0_14px] shadow-warning/50' : 'bg-card text-warning border-warning hover:bg-warning-muted')}>
            {kpa.operate ? 'OPERATE' : 'STANDBY'}
          </button>
          {/* The amplifier answers while its main supplies are off — a sleeping
              microcontroller stays awake for exactly that — so ON is offered
              over the network as well, unlike the SPE and Acom. */}
          <div className="inline-flex rounded-lg overflow-hidden border-2 border-success/70">
            <button type="button" disabled={!kpa.connected}
              onClick={() => AmpPower(amp.id, true).catch(() => {})}
              className="px-3 py-2 text-sm font-bold bg-card text-success hover:bg-success/15 disabled:opacity-30">ON</button>
            <button type="button" disabled={!kpa.connected}
              onClick={() => AmpPower(amp.id, false).catch(() => {})}
              className="px-3 py-2 text-sm font-bold bg-card text-danger border-l-2 border-success/70 hover:bg-danger/15 disabled:opacity-30">OFF</button>
          </div>
          <span className={cn('inline-flex items-center gap-1.5 text-sm', kpa.connected ? 'text-muted-foreground' : 'text-danger')}>
            <span className={cn('size-2 rounded-full', kpa.connected ? 'bg-success' : 'bg-danger')} />
            {kpa.connected ? (kpa.tuning ? t('flxp.kpaTuning') : (kpa.power_on ? 'ON' : 'OFF')) : t('flxp.kpaOffline')}
          </span>
          {kpa.connected && (
            <span className="text-sm font-mono text-muted-foreground tabular-nums">
              {kpa.band ? `${kpa.band} · ` : ''}{kpa.fwd_w}W · SWR {Number(kpa.swr ?? 0).toFixed(1)} · {kpa.temp_c}°C · {kpa.volt_v}V {kpa.cur_a}A
            </span>
          )}
          <div className="flex-1" />
          {kpa.fault_text && (
            <span className="px-2 py-1 rounded bg-danger-muted text-danger-muted-foreground text-xs font-bold">⚠ {kpa.fault_text}</span>
          )}
        </div>
        {kpa.connected && (
          <MeterBar label={t('flxp.outputPower')} value={Number(kpa.fwd_w) || 0} unit="W"
            lo={0} hi={String(kpa.model).includes('500') ? 500 : 1500}
            display={`${Number(kpa.fwd_w) || 0} W`}
            segColor={(f) => (f > 0.9 ? '#dc2626' : f > 0.75 ? '#f59e0b' : '#ea580c')} />
        )}
      </Card>
    );
  }

  // PowerGenius XL — OPERATE + meters ride on the Flex; fan mode on the GSCP link.
  const pg = amp.pgxl || {};
  const viaFlex = !!flex?.amp_available;
  const operate = viaFlex ? !!flex?.amp_operate : !!pg.operate;
  const connected = !!pg.connected || viaFlex;
  const fault = flex?.amp_fault;

  // Meters built from the amplifier's own GSCP status frame, for when the radio
  // is not feeding a meter stream.
  //
  // Whether there is power is the amp's state field; how much is the plain
  // forward figure. NOT "peakfwd" — that is a latched maximum which is never
  // reset and survives in the last-known status after the amp disconnects, so it
  // once claimed 1350 W from an old transmission while 10 W was going out. Same
  // reason peak_id is left alone. Both readings are gated on transmit so they
  // fall back to zero between overs instead of freezing on the last one.
  const pgxlMeters = () => {
    if (!pg.connected) return null;
    const txing = typeof flex?.transmitting === 'boolean' ? flex.transmitting : /TRANSMIT/i.test(pg.state || '');
    const fwdW = peakHold('pgfwd', txing ? Number(pg.fwd_w) || 0 : 0);
    const idA = peakHold('pgid', txing ? Number(pg.id) || 0 : 0);
    const swr = peakHold('pgswr', txing ? Number(pg.vswr) || 0 : 0);
    const tempC = Number(pg.temperature) || 0;
    // Two columns, not four. The card sits beside a tall neighbour in Station
    // Control, so a single row of four leaves the height empty and squeezes each
    // bar into a quarter width — two rows of two use the room that is already
    // there and give every bar twice the resolution.
    return (
      <div className="grid grid-cols-2 gap-2 mt-2 pt-2 border-t border-border/50">
        <MeterBar label={t('flxp.outputPower')} value={fwdW} unit="W" lo={0} hi={2000}
          display={`${Math.round(fwdW)} W`}
          segColor={(f) => (f > 0.9 ? '#dc2626' : f > 0.75 ? '#f59e0b' : '#ea580c')} />
        <MeterBar label={t('ampw.id')} value={idA} lo={0} hi={25} display={`${idA.toFixed(1)} A`} accent="#16a34a" />
        {/* Below 1:1 the reading is meaningless, so an idle amp shows a flat bar
            rather than a zero that looks like a perfect match. */}
        <MeterBar label={t('ampw.swr')} value={swr >= 1 ? swr : 1} lo={1} hi={3}
          display={swr >= 1 ? swr.toFixed(1) : '—'}
          segColor={(f) => (f > 0.75 ? '#dc2626' : f > 0.4 ? '#f59e0b' : '#16a34a')} />
        <MeterBar label={t('ampw.temp')} value={tempC} unit="°C" lo={0} hi={100}
          display={tempC > 0 ? `${Math.round(tempC)} °C` : '—'}
          segColor={(f) => (f > 0.8 ? '#dc2626' : f > 0.6 ? '#f59e0b' : '#ea580c')} />
      </div>
    );
  };

  return (
    <Card icon={Flame} ckey="amplifier" title={`${t('flxp.amplifier')}${flex?.amp_model ? ' · ' + flex.amp_model : (pg.model ? ' · ' + pg.model : '')} · ${amp.name}`} accent="#ea580c">
      <div className="flex items-center gap-3 flex-wrap">
        <button type="button" disabled={!connected}
          onClick={() => (viaFlex ? FlexAmpOperate(!operate) : AmpOperate(amp.id, !operate)).catch(() => {})}
          className={cn('px-4 py-2 rounded-lg text-sm font-extrabold tracking-wide border-2 transition-all disabled:opacity-30',
            operate ? 'bg-warning text-warning-foreground border-warning shadow-[0_0_14px] shadow-warning/50' : 'bg-card text-warning border-warning hover:bg-warning-muted')}>
          {operate ? 'OPERATE' : 'STANDBY'}
        </button>
        {(pg.host || pg.connected) && (
          <label className="flex items-center gap-1.5 text-xs" title={pg.connected ? t('flxp.pgConnected') : (pg.last_error || t('flxp.pgOffline'))}>
            <span className={cn('size-1.5 rounded-full', pg.connected ? 'bg-success shadow-[0_0_6px_rgba(16,185,129,0.8)]' : 'bg-danger')} />
            <span className="text-muted-foreground">{t('flxp.fan')}</span>
            <select
              disabled={!pg.connected}
              value={(pg.fan_mode || 'CONTEST').toUpperCase()}
              onChange={(e) => AmpFanMode(amp.id, e.target.value).catch(() => {})}
              className="h-8 rounded-md border border-warning-border bg-card px-2 text-xs font-semibold text-warning outline-none focus:border-warning disabled:opacity-40"
            >
              <option value="STANDARD">{t('flxp.fanStandard')}</option>
              <option value="CONTEST">{t('flxp.fanContest')}</option>
              <option value="BROADCAST">{t('flxp.fanBroadcast')}</option>
            </select>
          </label>
        )}
        <div className="flex-1" />
        {fault && fault !== 'NONE' && (
          <span className="px-2 py-1 rounded bg-danger-muted text-danger-muted-foreground text-xs font-bold">{t('flxp.fault')}: {fault}</span>
        )}
      </div>
      {/* Amplifier meters (FWD / ID / TEMP …).
          The FlexRadio UDP stream is the preferred source — it is fast and reads
          the same as SmartSDR. When there is no Flex, or it is not streaming,
          the amplifier's OWN link carries the same figures; falling back to them
          is what the docked widget already does. Without that fallback this card
          showed an operator on a Kenwood nothing but OPERATE and the fan mode,
          while the amplifier was reporting power, current and temperature all
          along. */}
      {(() => {
        const meters = (flex?.meters as any[]) || [];
        const dbmToW = (d: number) => Math.pow(10, (d - 30) / 10);
        const amps = meters.filter((m) => (m.src || '').toUpperCase().includes('AMP')
          && !/^(RL|DRV)$/i.test((m.name || '').trim()));
        if (!viaFlex || amps.length === 0) return pgxlMeters();
        // Power comes from the radio's meter stream and nothing else. The
        // amplifier also reports a "peakfwd", and using it was a mistake twice
        // over: it is a latched maximum that is never reset, and it survives in
        // the last-known status after the amp disconnects — so it claimed
        // 1350 W from an old transmission while the radio was putting out 10.
        return (
          <div className="grid grid-cols-2 sm:grid-cols-3 gap-2 mt-2 pt-2 border-t border-border/50">
            {amps.map((m) => {
              if (/fwd|pwr/i.test(m.name || '') && /dbm/i.test(m.unit || '')) {
                return <MeterBar key={m.id} label={m.name || `AMP ${m.id}`} value={peakHold(`amp${m.id}`, dbmToW(m.value))} unit="W" lo={0} hi={2000} accent="#dc2626" />;
              }
              const acc = /temp|degc|degf/i.test(`${m.unit}${m.name}`) ? '#ea580c' : /volt/i.test(m.unit || '') ? '#2563eb' : '#16a34a';
              let lo = m.lo, hi = m.hi;
              if (/amp/i.test(m.unit || '') || /^ID$|current/i.test(m.name || '')) {
                lo = 0;
                hi = m.hi >= 25 ? m.hi : 25;
              }
              return <MeterBar key={m.id} label={m.name || `AMP ${m.id}`} value={peakHold(`amp${m.id}`, m.value)} unit={m.unit} lo={lo} hi={hi} accent={acc} />;
            })}
          </div>
        );
      })()}
    </Card>
  );
}
