'use client';

/**
 * ProfileChannelsSection — Channels Card (CHAN-02..CHAN-05, CHAN-07).
 *
 * Two sub-sections separated by a Separator:
 *   1. Teams — webhook URL input + Save / Clear buttons + inline test result
 *   2. ntfy  — mint-on-first-save + QR code + advanced topic override
 *
 * Each sub-section saves independently (no global Save).
 * Inline errors display the server response body's `message` / `error` string
 * on non-2xx, cleared on next successful save.
 */

import { useEffect, useState } from 'react';
import { toast } from 'sonner';
import { CheckCircle, XCircle } from 'lucide-react';
import { QRCodeSVG } from 'qrcode.react';
import {
  Card,
  CardHeader,
  CardTitle,
  CardDescription,
  CardContent,
} from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { Separator } from '@/components/ui/separator';

// Personal ntfy channels target the company ntfy instance. The fallback
// matches the server-side default in personal-channels.ts / notify.ts so
// the UI and the publish path stay aligned even when the env var is unset
// in a dev shell (UAT-FIX-01).
const NTFY_BASE = process.env.NEXT_PUBLIC_NTFY_BASE_URL || 'https://ntfy.wulfconsulting.cloud';

// ── Types ────────────────────────────────────────────────────────────────────

interface Channel {
  id: string;
  name: string;
  channelType: string;
  config: Record<string, string>;
  isActive: boolean;
  ownerUserId: string;
  createdAt: string;
  updatedAt: string;
}

interface ChannelTestResult {
  ok: boolean;
  status?: number;
  error?: string;
}

interface ChannelsState {
  teams?: Channel;
  ntfy?: Channel;
}

// ── Inline test result row ────────────────────────────────────────────────────

function TestResultRow({ test }: { test: ChannelTestResult }) {
  if (test.ok) {
    return (
      <div className="flex items-center gap-2 text-xs">
        <CheckCircle className="w-3.5 h-3.5 text-green-600" />
        <span className="text-green-600">Channel verified</span>
      </div>
    );
  }
  return (
    <div className="flex items-center gap-2 text-xs">
      <XCircle className="w-3.5 h-3.5 text-destructive" />
      <span className="text-destructive">
        Test failed — {test.status ?? test.error ?? 'unknown'}
      </span>
    </div>
  );
}

// ── Main component ────────────────────────────────────────────────────────────

export function ProfileChannelsSection() {
  const [loading, setLoading] = useState(true);
  const [channels, setChannels] = useState<ChannelsState>({});

  // Teams state
  const [teamsInput, setTeamsInput] = useState('');
  const [teamsTest, setTeamsTest] = useState<ChannelTestResult | null>(null);
  const [teamsError, setTeamsError] = useState<string | null>(null);

  // ntfy state
  const [ntfyTest, setNtfyTest] = useState<ChannelTestResult | null>(null);
  const [customTopicInput, setCustomTopicInput] = useState('');
  const [customTopicError, setCustomTopicError] = useState<string | null>(null);

  // ── Load channels on mount ────────────────────────────────────────────────

  useEffect(() => {
    fetch('/api/me/channels')
      .then((r) => r.json())
      .then((data: { channels: Channel[] }) => {
        const teams = data.channels.find((c) => c.channelType === 'teams');
        const ntfy = data.channels.find((c) => c.channelType === 'ntfy');
        setChannels({ teams, ntfy });
        if (teams?.config?.webhook_url) {
          setTeamsInput(teams.config.webhook_url);
        }
        if (ntfy?.config?.topic) {
          setCustomTopicInput(ntfy.config.topic);
        }
      })
      .catch(() => toast.error('Failed to load channels'))
      .finally(() => setLoading(false));
  }, []);

  // ── Teams handlers ────────────────────────────────────────────────────────

  const saveTeams = async () => {
    setTeamsError(null);
    const resp = await fetch('/api/me/channels/teams', {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ webhook_url: teamsInput }),
    });
    const body = await resp.json().catch(() => ({}));
    if (!resp.ok) {
      setTeamsError(body.message || body.error || `Save failed (${resp.status})`);
      toast.error('Failed to save channel');
      return;
    }
    setChannels((c) => ({ ...c, teams: body.channel }));
    setTeamsTest(body.test);
    toast.success('Channel saved');
  };

  const clearTeams = async () => {
    await fetch('/api/me/channels/teams', { method: 'DELETE' });
    setChannels((c) => ({ ...c, teams: undefined }));
    setTeamsInput('');
    setTeamsTest(null);
    setTeamsError(null);
    toast.success('Channel removed');
  };

  // ── ntfy handlers ─────────────────────────────────────────────────────────

  const enableNtfy = async () => {
    const resp = await fetch('/api/me/channels/ntfy', {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({}),
    });
    const data = await resp.json().catch(() => ({}));
    if (!resp.ok) {
      toast.error('Failed to save channel');
      return;
    }
    setChannels((c) => ({ ...c, ntfy: data.channel }));
    setNtfyTest(data.test);
    if (data.channel?.config?.topic) {
      setCustomTopicInput(data.channel.config.topic);
    }
    toast.success('Channel saved');
  };

  const saveCustomTopic = async () => {
    setCustomTopicError(null);
    const resp = await fetch('/api/me/channels/ntfy', {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ topic: customTopicInput }),
    });
    const body = await resp.json().catch(() => ({}));
    if (!resp.ok) {
      setCustomTopicError(body.message || body.error || `Save failed (${resp.status})`);
      toast.error('Failed to save channel');
      return;
    }
    setChannels((c) => ({ ...c, ntfy: body.channel }));
    setNtfyTest(body.test);
    setCustomTopicError(null);
    toast.success('Channel saved');
  };

  const testNtfy = async () => {
    const resp = await fetch('/api/me/channels/ntfy/test', { method: 'POST' });
    const data = await resp.json().catch(() => ({}));
    if (data.test) {
      setNtfyTest(data.test);
    }
  };

  const removeNtfy = async () => {
    await fetch('/api/me/channels/ntfy', { method: 'DELETE' });
    setChannels((c) => ({ ...c, ntfy: undefined }));
    setNtfyTest(null);
    setCustomTopicInput('');
    setCustomTopicError(null);
    toast.success('Channel removed');
  };

  // ── Render ────────────────────────────────────────────────────────────────

  if (loading) {
    return (
      <Card>
        <CardHeader className="px-4 pt-4 pb-0">
          <CardTitle>Personal Channels</CardTitle>
        </CardHeader>
        <CardContent className="px-4 py-4">
          <div className="space-y-3">
            <div className="h-10 w-full rounded bg-muted animate-pulse" />
            <div className="h-10 w-full rounded bg-muted animate-pulse" />
          </div>
        </CardContent>
      </Card>
    );
  }

  const ntfyTopic = channels.ntfy?.config?.topic;

  return (
    <Card>
      <CardHeader className="px-4 pt-4 pb-0">
        <CardTitle>Personal Channels</CardTitle>
        <CardDescription>Receive notifications directly on your devices.</CardDescription>
      </CardHeader>
      <CardContent className="px-4 py-4 space-y-4">

        {/* ── Teams sub-section ──────────────────────────────────────────── */}
        <div className="space-y-2">
          <Label htmlFor="teams-webhook-url">Microsoft Teams webhook URL</Label>
          <Input
            id="teams-webhook-url"
            placeholder="https://yourorg.webhook.office.com/..."
            value={teamsInput}
            onChange={(e) => {
              setTeamsInput(e.target.value);
              setTeamsError(null);
            }}
          />
          {teamsError && (
            <p className="text-xs text-destructive">{teamsError}</p>
          )}
          {teamsTest && <TestResultRow test={teamsTest} />}
          <div className="flex gap-2 pt-1">
            <Button
              onClick={saveTeams}
              className="min-h-[44px]"
            >
              Save Teams URL
            </Button>
            <Button
              variant="ghost"
              onClick={clearTeams}
              className="text-destructive min-h-[44px]"
            >
              Clear
            </Button>
          </div>
        </div>

        <Separator className="my-4" />

        {/* ── ntfy sub-section ───────────────────────────────────────────── */}
        <div className="space-y-2">
          <Label>Mobile push (ntfy)</Label>

          {!ntfyTopic ? (
            /* State A — no topic yet */
            <>
              <p className="text-sm text-muted-foreground">
                Pulse will generate a private topic for you.
              </p>
              <Button
                className="w-full min-h-[44px]"
                onClick={enableNtfy}
              >
                Enable mobile push
              </Button>
            </>
          ) : (
            /* State B — topic minted */
            <div className="space-y-3">
              <a
                href={`${NTFY_BASE}/${ntfyTopic}`}
                target="_blank"
                rel="noopener noreferrer"
                className="text-primary text-sm underline break-all"
              >
                {`${NTFY_BASE}/${ntfyTopic}`}
              </a>

              <div
                role="img"
                aria-label={`Subscribe to ${ntfyTopic} on ntfy`}
                className="flex justify-center"
              >
                <QRCodeSVG value={`${NTFY_BASE}/${ntfyTopic}`} size={200} />
              </div>

              <p className="text-xs text-muted-foreground">
                Scan with the ntfy app to subscribe.
              </p>

              {ntfyTest && <TestResultRow test={ntfyTest} />}

              <details>
                <summary className="text-sm text-primary cursor-pointer">
                  Edit advanced
                </summary>
                <div className="space-y-2 pt-2">
                  <Label htmlFor="custom-ntfy-topic">Custom ntfy topic</Label>
                  <Input
                    id="custom-ntfy-topic"
                    value={customTopicInput}
                    onChange={(e) => {
                      setCustomTopicInput(e.target.value);
                      setCustomTopicError(null);
                    }}
                  />
                  <p className="text-xs text-muted-foreground">
                    Topic must start with <code>pulse-me-</code>.
                  </p>
                  {customTopicError && (
                    <p className="text-xs text-destructive">{customTopicError}</p>
                  )}
                  <Button
                    onClick={saveCustomTopic}
                    className="min-h-[44px]"
                  >
                    Save custom topic
                  </Button>
                </div>
              </details>

              <div className="flex gap-2 pt-1">
                <Button
                  onClick={testNtfy}
                  className="min-h-[44px]"
                >
                  Test now
                </Button>
                <Button
                  variant="ghost"
                  onClick={removeNtfy}
                  className="text-destructive min-h-[44px]"
                >
                  Remove
                </Button>
              </div>
            </div>
          )}
        </div>
      </CardContent>
    </Card>
  );
}
