import { useState, useEffect, useCallback } from 'react';
import { useOutletContext } from 'react-router-dom';
import {
  Card, Button, Form, Input, Space, Table, Tag, Typography, Spin, Alert, Descriptions, App,
  Drawer, Checkbox, Select, Popconfirm, Grid, Steps, Tooltip, Collapse,
} from 'antd';
import {
  CloudServerOutlined, SyncOutlined, CheckCircleOutlined, CloseCircleOutlined,
  RocketOutlined, ExclamationCircleOutlined, ReloadOutlined, PoweroffOutlined,
} from '@ant-design/icons';
import { api } from '@/lib/api';
import type { AppOutletContext } from '@/components/AppLayout';
import type {
  PangolinStatus, PangolinConfig, PangolinResource, PangolinNewtStatus, PangolinExitNode,
  PangolinSite, ConnectSiteResult, ResourceStatusResponse, ResourceStatusItem, SyncResult,
} from '@/types/api';

const { Text, Paragraph } = Typography;

// Simple text sanitizer for external API data (defense-in-depth)
const sanitizeText = (text: string | undefined): string => {
  if (!text) return '';
  return text.replace(/[<>'"&]/g, (char) => {
    const escapeMap: Record<string, string> = {
      '<': '&lt;',
      '>': '&gt;',
      "'": '&#39;',
      '"': '&quot;',
      '&': '&amp;',
    };
    return escapeMap[char] || char;
  });
};

interface SetupResult {
  success: boolean;
  site?: { siteId: string; name: string };
  newt?: {
    newtId: string | null;
    credentialsAutoWritten: boolean;
    containerRestarted: boolean;
  };
  resources?: {
    created: number;
    total: number;
    items: Array<{ subdomain: string; name: string; resourceId: string; targetCreated: boolean }>;
    errors: string[];
    warnings: string[];
  };
  envUpdate?: {
    success: boolean;
    updated: string[];
    added: string[];
    error?: string;
  };
  manualInstructions?: string[];
}

export default function PangolinPage() {
  const { setPageHeader } = useOutletContext<AppOutletContext>();
  const { message } = App.useApp();
  const screens = Grid.useBreakpoint();
  const isMobile = !screens.md;

  const [status, setStatus] = useState<PangolinStatus | null>(null);
  const [config, setConfig] = useState<PangolinConfig | null>(null);
  const [loading, setLoading] = useState(true);
  const [actionLoading, setActionLoading] = useState(false);
  const [setupResult, setSetupResult] = useState<SetupResult | null>(null);
  const [editDrawerOpen, setEditDrawerOpen] = useState(false);
  const [editingResource, setEditingResource] = useState<PangolinResource | null>(null);
  const [editForm] = Form.useForm();
  const [newtStatus, setNewtStatus] = useState<PangolinNewtStatus | null>(null);
  const [newtLoading, setNewtLoading] = useState(false);
  const [restartLoading, setRestartLoading] = useState(false);
  const [setupForm] = Form.useForm();
  const [exitNodes, setExitNodes] = useState<PangolinExitNode[]>([]);
  const [exitNodesLoading, setExitNodesLoading] = useState(false);
  const [setupStep, setSetupStep] = useState(-1); // -1 = not started
  const [resourceDefinitions, setResourceDefinitions] = useState<Array<{
    name: string;
    subdomain: string;
    fullDomain: string;
    port: number;
    container: string;
    target_ip: string;
    target_port: number;
    required: boolean;
  }>>([]);
  const [resourceStatus, setResourceStatus] = useState<ResourceStatusResponse | null>(null);
  const [statusLoading, setStatusLoading] = useState(false);
  const [syncResult, setSyncResult] = useState<SyncResult | null>(null);
  const [orgSites, setOrgSites] = useState<(PangolinSite & { isCurrentSite?: boolean })[]>([]);
  const [sitesLoading, setSitesLoading] = useState(false);
  const [connectLoading, setConnectLoading] = useState<string | null>(null); // siteId being connected

  useEffect(() => {
    setPageHeader({ title: 'Tunnel Management' });
    return () => setPageHeader(null);
  }, [setPageHeader]);

  const fetchData = useCallback(async () => {
    setLoading(true);
    try {
      const [statusRes, configRes, resourceDefsRes] = await Promise.all([
        api.get<PangolinStatus>('/pangolin/status'),
        api.get<PangolinConfig>('/pangolin/config'),
        api.get<{ domain: string; resources: Array<{ name: string; subdomain: string; fullDomain: string; port: number; container: string; target_ip: string; target_port: number; required: boolean }> }>('/pangolin/resource-definitions'),
      ]);
      setStatus(statusRes.data);
      setConfig(configRes.data);
      setResourceDefinitions(resourceDefsRes.data.resources);
    } catch {
      message.error('Failed to load Pangolin status');
    } finally {
      setLoading(false);
    }
  }, [message]);

  useEffect(() => { fetchData(); }, [fetchData]);

  const fetchNewtStatus = useCallback(async () => {
    if (!status?.newtConfigured) return;

    setNewtLoading(true);
    try {
      const res = await api.get<PangolinNewtStatus>('/pangolin/newt-status');
      setNewtStatus(res.data);
    } catch {
      // Silently fail
    } finally {
      setNewtLoading(false);
    }
  }, [status?.newtConfigured]);

  useEffect(() => {
    if (status?.newtConfigured) {
      fetchNewtStatus();
    }
  }, [status?.newtConfigured, fetchNewtStatus]);

  // Fetch live resource status (cross-referenced YAML vs Pangolin)
  const fetchResourceStatus = useCallback(async () => {
    setStatusLoading(true);
    try {
      const res = await api.get<ResourceStatusResponse>('/pangolin/resource-status');
      setResourceStatus(res.data);
    } catch {
      // Silently fail — status card will show loading state
    } finally {
      setStatusLoading(false);
    }
  }, []);

  useEffect(() => {
    if (status?.configured && config?.siteId) {
      fetchResourceStatus();
    }
  }, [status?.configured, config?.siteId, fetchResourceStatus]);

  // Fetch org sites when site ID is stale/missing (for site picker)
  const fetchOrgSites = useCallback(async () => {
    setSitesLoading(true);
    try {
      const res = await api.get<{ sites: (PangolinSite & { isCurrentSite?: boolean })[]; currentNewtId: string | null }>('/pangolin/sites');
      setOrgSites(res.data.sites);
    } catch {
      message.error('Failed to load sites from Pangolin');
    } finally {
      setSitesLoading(false);
    }
  }, [message]);

  useEffect(() => {
    // Load org sites when: configured but site ID is stale/missing (for site picker)
    if (status?.configured && (status?.siteIdMismatch || !config?.siteId)) {
      fetchOrgSites();
    }
  }, [status?.configured, status?.siteIdMismatch, config?.siteId, fetchOrgSites]);

  const handleConnectSite = async (siteId: string) => {
    setConnectLoading(siteId);
    try {
      const res = await api.post<ConnectSiteResult>('/pangolin/connect-site', { siteId });
      if (res.data.success) {
        message.success(res.data.message);
        // Refresh everything after connecting
        setTimeout(() => {
          fetchData();
          fetchNewtStatus();
        }, 1500);
      }
    } catch (err: unknown) {
      const msg = (err as { response?: { data?: { error?: { message?: string } } } })?.response?.data?.error?.message ?? 'Failed to connect to site';
      message.error(msg);
    } finally {
      setConnectLoading(null);
    }
  };

  // Fetch exit nodes for site creation
  useEffect(() => {
    if (status?.configured && !config?.siteId) {
      setExitNodesLoading(true);
      api.get<{ exitNodes: PangolinExitNode[] }>('/pangolin/exit-nodes')
        .then(res => {
          setExitNodes(res.data.exitNodes);
          const onlineNodes = res.data.exitNodes.filter(n => n.online);
          if (onlineNodes.length === 1 && onlineNodes[0]) {
            setupForm.setFieldsValue({ exitNodeId: onlineNodes[0].exitNodeId });
          }
        })
        .catch(() => {
          // Exit nodes not available - OK for self-hosted
        })
        .finally(() => setExitNodesLoading(false));
    }
  }, [status?.configured, config?.siteId, setupForm]);

  const handleSetup = async (values: { siteName?: string; exitNodeId?: string }) => {
    setActionLoading(true);
    setSetupStep(0);
    try {
      const res = await api.post<SetupResult>('/pangolin/setup', {
        siteName: values.siteName,
        exitNodeId: values.exitNodeId,
        autoWriteEnv: true,
      });

      const result = res.data;
      setSetupResult(result);

      // Animate through steps based on result
      if (result.site?.siteId) setSetupStep(1);
      if (result.resources && result.resources.created > 0) setSetupStep(2);
      if (result.envUpdate?.success) setSetupStep(3);
      if (result.newt?.containerRestarted) setSetupStep(4);

      if (result.newt?.credentialsAutoWritten) {
        message.success('Setup complete! Credentials auto-written to .env and Newt restarted.');
      } else if (result.manualInstructions) {
        message.warning('Site created but .env auto-write failed. See manual instructions below.');
      } else {
        message.success('Setup complete!');
      }

      // Refresh data after setup
      setTimeout(() => {
        fetchData();
        fetchNewtStatus();
      }, 3000);
    } catch (err: unknown) {
      const msg = (err as { response?: { data?: { error?: { message?: string } } } })?.response?.data?.error?.message ?? 'Setup failed';
      message.error(msg);
      setSetupStep(-1);
    } finally {
      setActionLoading(false);
    }
  };

  const handleSync = async () => {
    setActionLoading(true);
    setSyncResult(null);
    try {
      const res = await api.post<SyncResult>('/pangolin/sync');
      const data = res.data;
      setSyncResult(data);
      if (data.errors > 0) {
        message.warning(`Sync complete with ${data.errors} error(s)`);
      } else {
        message.success(`Sync complete: ${data.created} created, ${data.targetFixed} targets fixed, ${data.skipped} unchanged`);
      }
      // Auto-refresh resource status after sync
      setTimeout(() => fetchResourceStatus(), 1500);
    } catch (err: unknown) {
      const msg = (err as { response?: { data?: { error?: { message?: string } } } })?.response?.data?.error?.message ?? 'Sync failed';
      message.error(msg);
    } finally {
      setActionLoading(false);
    }
  };

  const handleUpdateResource = async (values: Record<string, unknown>) => {
    if (!editingResource) return;

    setActionLoading(true);
    try {
      await api.put(`/pangolin/resource/${editingResource.resourceId}`, values);
      message.success('Resource updated');
      setEditDrawerOpen(false);
      setEditingResource(null);
      editForm.resetFields();
      fetchData();
    } catch {
      message.error('Failed to update resource');
    } finally {
      setActionLoading(false);
    }
  };

  const handleRestartNewt = async () => {
    setRestartLoading(true);
    try {
      await api.post('/pangolin/newt-restart');
      message.success('Newt container restarted. Checking status...');
      setTimeout(() => fetchNewtStatus(), 3000);
    } catch (err: unknown) {
      const msg = (err as { response?: { data?: { error?: { message?: string } } } })?.response?.data?.error?.message || 'Failed to restart container';
      message.error(msg);
    } finally {
      setRestartLoading(false);
    }
  };

  if (loading) {
    return <Spin size="large" style={{ display: 'block', margin: '100px auto' }} />;
  }

  const isConfigured = status?.configured;
  const isHealthy = status?.healthy;
  const drawerWidth = isMobile ? 0 : 600;

  return (
    <Space direction="vertical" size="large" style={{ width: '100%', marginRight: editDrawerOpen ? drawerWidth : 0, transition: 'margin-right 0.15s cubic-bezier(0.2, 0, 0, 1)' }}>
      {/* Status Card */}
      <Card title={<><CloudServerOutlined /> Pangolin Tunnel Status</>}>
        <Descriptions column={{ xs: 1, sm: 2 }} bordered size="small">
          <Descriptions.Item label="Configured">
            {isConfigured
              ? <Tag icon={<CheckCircleOutlined />} color="success">Yes</Tag>
              : <Tag icon={<CloseCircleOutlined />} color="error">No</Tag>}
          </Descriptions.Item>
          <Descriptions.Item label="Server Health">
            {isHealthy
              ? <Tag icon={<CheckCircleOutlined />} color="success">Healthy</Tag>
              : <Tag icon={<CloseCircleOutlined />} color="error">Unreachable</Tag>}
          </Descriptions.Item>
          <Descriptions.Item label="API URL">
            <Text copyable>{config?.pangolinApiUrl || 'Not set'}</Text>
          </Descriptions.Item>
          <Descriptions.Item label="Newt Container">
            {newtLoading ? (
              <Spin size="small" />
            ) : newtStatus?.ready ? (
              <Tag icon={<CheckCircleOutlined />} color="success">Ready</Tag>
            ) : newtStatus?.containerRunning ? (
              <Tag color="warning">Running (Not configured)</Tag>
            ) : status?.newtConfigured ? (
              <Tag color="error">Stopped</Tag>
            ) : (
              <Tag color="default">Not configured</Tag>
            )}
          </Descriptions.Item>
          <Descriptions.Item label="Organization ID">
            <Text code>{config?.orgId || 'Not set'}</Text>
          </Descriptions.Item>
          <Descriptions.Item label="Site ID">
            <Space>
              <Text code>{config?.siteId || 'Not set'}</Text>
              {status?.siteIdMismatch && (
                <Tag icon={<ExclamationCircleOutlined />} color="warning">Stale</Tag>
              )}
              {status?.siteIdValid === true && (
                <Tag icon={<CheckCircleOutlined />} color="success">Valid</Tag>
              )}
            </Space>
          </Descriptions.Item>
        </Descriptions>
      </Card>

      {/* Site Picker — shown when site ID is stale or mismatched */}
      {isConfigured && status?.siteIdMismatch && (
        <Card title={<><ExclamationCircleOutlined /> Site ID Mismatch</>}>
          <Alert
            type="warning"
            showIcon
            message="Your PANGOLIN_SITE_ID no longer matches this organization"
            description={
              <div>
                <Paragraph>
                  The site ID <Text code>{config?.siteId}</Text> in your <Text code>.env</Text> file
                  {status?.resolvedSiteId
                    ? <> does not match the detected site <Text code>{status.resolvedSiteId}</Text>.</>
                    : <> was not found in the organization.</>
                  }
                  {' '}The Newt tunnel may still be working, but resource management (sync, status checks) will fail.
                </Paragraph>
                <Paragraph>Select the correct site below to fix this:</Paragraph>
              </div>
            }
            style={{ marginBottom: 16 }}
          />
          <Table<PangolinSite & { isCurrentSite?: boolean }>
            dataSource={orgSites}
            rowKey="siteId"
            size="small"
            loading={sitesLoading}
            pagination={false}
            columns={[
              {
                title: 'Site Name',
                dataIndex: 'name',
                key: 'name',
                render: (name: string, record) => (
                  <Space>
                    <Text strong>{sanitizeText(name)}</Text>
                    {record.isCurrentSite && <Tag color="blue">Matches Newt ID</Tag>}
                  </Space>
                ),
              },
              {
                title: 'Site ID',
                dataIndex: 'siteId',
                key: 'siteId',
                render: (id: string) => <Text code>{id}</Text>,
              },
              ...(!isMobile ? [{
                title: 'Status',
                key: 'online',
                width: 100,
                render: (_: unknown, record: PangolinSite) =>
                  record.online
                    ? <Tag color="success">Online</Tag>
                    : <Tag color="default">Offline</Tag>,
              }] : []),
              ...(!isMobile ? [{
                title: 'Last Seen',
                dataIndex: 'lastSeen',
                key: 'lastSeen',
                render: (d: string) => d ? new Date(d).toLocaleString() : '—',
              }] : []),
              {
                title: '',
                key: 'action',
                width: 120,
                render: (_: unknown, record: PangolinSite) => (
                  <Button
                    type={record.isCurrentSite ? 'primary' : 'default'}
                    size="small"
                    loading={connectLoading === record.siteId}
                    onClick={() => handleConnectSite(record.siteId)}
                  >
                    Connect
                  </Button>
                ),
              },
            ]}
          />
          <div style={{ marginTop: 12 }}>
            <Button icon={<ReloadOutlined />} loading={sitesLoading} onClick={fetchOrgSites} size="small">
              Refresh Sites
            </Button>
          </div>
        </Card>
      )}

      {/* Setup Card — shown when API credentials configured but no site yet */}
      {isConfigured && !config?.siteId && (
        <Card title={<><RocketOutlined /> Automated Setup</>}>
          <Alert
            type="info"
            showIcon
            message="One-Click Setup"
            description="This will automatically create a Pangolin site, configure all resources with targets, write credentials to .env, and restart the Newt container."
            style={{ marginBottom: 16 }}
          />

          <div style={{ maxWidth: 600 }}>
            <Form form={setupForm} layout="vertical" onFinish={handleSetup}>
              <Form.Item name="siteName" label="Site Name">
                <Input placeholder={`changemaker-${config?.domain || 'cmlite.org'}`} />
              </Form.Item>

              {exitNodes.length > 0 && (
                <Form.Item
                  name="exitNodeId"
                  label="Exit Node (optional)"
                  tooltip="Network exit point for tunneled traffic. Only needed for multi-node setups."
                >
                  <Select
                    placeholder="Select an exit node (optional)"
                    allowClear
                    loading={exitNodesLoading}
                    disabled={exitNodesLoading}
                    showSearch
                    optionFilterProp="children"
                  >
                    {exitNodes.map(node => (
                      <Select.Option
                        key={node.exitNodeId}
                        value={node.exitNodeId}
                        disabled={!node.online}
                      >
                        {sanitizeText(node.name)}
                        {node.location && ` (${sanitizeText(node.location)})`}
                        {!node.online && ' [OFFLINE]'}
                      </Select.Option>
                    ))}
                  </Select>
                </Form.Item>
              )}

              {exitNodes.length === 0 && (
                <Alert
                  message="Self-Hosted Mode"
                  description="No exit nodes detected. Site will be created without an exit node (standard for self-hosted Pangolin)."
                  type="info"
                  showIcon
                  style={{ marginBottom: 16 }}
                />
              )}

              <Form.Item>
                <Button
                  type="primary"
                  htmlType="submit"
                  loading={actionLoading}
                  icon={<RocketOutlined />}
                  size="large"
                >
                  Run Automated Setup
                </Button>
              </Form.Item>
            </Form>
          </div>

          {/* Progress Steps */}
          {setupStep >= 0 && (
            <Steps
              current={setupStep}
              style={{ marginTop: 24 }}
              items={[
                { title: 'Fetch Credentials', description: 'pickSiteDefaults' },
                { title: 'Create Site', description: 'Newt tunnel site' },
                { title: 'Create Resources', description: 'HTTP proxy + targets' },
                { title: 'Write .env', description: 'Auto-configure' },
                { title: 'Restart Newt', description: 'Apply changes' },
              ]}
            />
          )}

          {/* Resources Preview */}
          <Paragraph strong style={{ marginTop: 24 }}>Resources to Create ({resourceDefinitions.length})</Paragraph>
          <Table
            dataSource={resourceDefinitions}
            scroll={{ x: 'max-content' }}
            rowKey="fullDomain"
            size="small"
            pagination={false}
            columns={[
              {
                title: 'Service',
                dataIndex: 'name',
                key: 'name',
                render: (name: string, record) => (
                  <Space>
                    <Text strong>{name}</Text>
                    {record.required && <Tag color="red">Required</Tag>}
                  </Space>
                ),
              },
              {
                title: 'Domain',
                dataIndex: 'fullDomain',
                key: 'fullDomain',
                render: (domain: string) => <Text code>{domain}</Text>,
              },
              {
                title: 'Target',
                key: 'target',
                render: (_: unknown, record) => (
                  <Text code>{record.target_ip}:{record.target_port}</Text>
                ),
              },
            ]}
          />

          {/* Connect to existing site — shown when org already has sites */}
          {orgSites.length > 0 && (
            <>
              <Paragraph strong style={{ marginTop: 24 }}>Or Connect to an Existing Site</Paragraph>
              <Alert
                type="info"
                message="Sites already exist in this organization. You can connect to one instead of creating a new one."
                style={{ marginBottom: 12 }}
              />
              <Table<PangolinSite & { isCurrentSite?: boolean }>
                dataSource={orgSites}
                rowKey="siteId"
                size="small"
                loading={sitesLoading}
                pagination={false}
                columns={[
                  {
                    title: 'Site Name',
                    dataIndex: 'name',
                    key: 'name',
                    render: (name: string, record) => (
                      <Space>
                        <Text strong>{sanitizeText(name)}</Text>
                        {record.isCurrentSite && <Tag color="blue">Matches Newt ID</Tag>}
                      </Space>
                    ),
                  },
                  {
                    title: 'Site ID',
                    dataIndex: 'siteId',
                    key: 'siteId',
                    render: (id: string) => <Text code>{id}</Text>,
                  },
                  ...(!isMobile ? [{
                    title: 'Status',
                    key: 'online',
                    width: 100,
                    render: (_: unknown, record: PangolinSite) =>
                      record.online
                        ? <Tag color="success">Online</Tag>
                        : <Tag color="default">Offline</Tag>,
                  }] : []),
                  {
                    title: '',
                    key: 'action',
                    width: 120,
                    render: (_: unknown, record: PangolinSite) => (
                      <Button
                        type={record.isCurrentSite ? 'primary' : 'default'}
                        size="small"
                        loading={connectLoading === record.siteId}
                        onClick={() => handleConnectSite(record.siteId)}
                      >
                        Connect
                      </Button>
                    ),
                  },
                ]}
              />
            </>
          )}
        </Card>
      )}

      {/* Step 1 Instructions — shown when NOT configured at all */}
      {!isConfigured && (
        <Card title={<><RocketOutlined /> Setup Required</>}>
          <Alert
            type="info"
            showIcon
            message="Step 1: Configure Pangolin API Credentials"
            description={
              <div>
                <Paragraph>Add these variables to your <Text code>.env</Text> file:</Paragraph>
                <pre style={{ background: 'rgba(0,0,0,0.1)', padding: 12, borderRadius: 6, fontSize: 12 }}>
                  PANGOLIN_API_URL=https://api.bnkserve.org/v1{'\n'}
                  PANGOLIN_API_KEY=your_api_key_here{'\n'}
                  PANGOLIN_ORG_ID=your_org_id
                </pre>
                <Paragraph>Then restart the API container:</Paragraph>
                <pre style={{ background: 'rgba(0,0,0,0.1)', padding: 12, borderRadius: 6, fontSize: 12 }}>
                  docker compose restart api
                </pre>
                <Paragraph type="secondary">
                  Once configured, return here to run the automated setup.
                </Paragraph>
              </div>
            }
          />
        </Card>
      )}

      {/* Setup Result */}
      {setupResult && (
        <Card title="Setup Result">
          {setupResult.newt?.credentialsAutoWritten ? (
            <Alert
              type="success"
              showIcon
              message="Setup Complete — Fully Automated"
              description={
                <div>
                  <Paragraph>
                    Site <Text code>{setupResult.site?.siteId}</Text> created with{' '}
                    <Text strong>{setupResult.resources?.created || 0}</Text> resources and targets.
                  </Paragraph>
                  <Paragraph>
                    Credentials have been automatically written to <Text code>.env</Text> and
                    the Newt container has been restarted.
                  </Paragraph>
                  {setupResult.resources?.items && setupResult.resources.items.length > 0 && (
                    <Table
                      dataSource={setupResult.resources.items}
                      scroll={{ x: 'max-content' }}
                      rowKey="resourceId"
                      size="small"
                      pagination={false}
                      style={{ marginTop: 12 }}
                      columns={[
                        { title: 'Service', dataIndex: 'name', key: 'name' },
                        { title: 'Subdomain', dataIndex: 'subdomain', key: 'subdomain', render: (s: string) => <Text code>{s}</Text> },
                        {
                          title: 'Target',
                          key: 'target',
                          render: (_: unknown, record) => (
                            record.targetCreated
                              ? <Tag icon={<CheckCircleOutlined />} color="success">Created</Tag>
                              : <Tag icon={<CloseCircleOutlined />} color="error">Failed</Tag>
                          ),
                        },
                      ]}
                    />
                  )}
                  {setupResult.resources?.errors && setupResult.resources.errors.length > 0 && (
                    <Alert
                      type="warning"
                      message={`${setupResult.resources.errors.length} error(s) during setup`}
                      description={setupResult.resources.errors.join('\n')}
                      style={{ marginTop: 12 }}
                    />
                  )}
                </div>
              }
            />
          ) : setupResult.manualInstructions ? (
            <Alert
              type="warning"
              showIcon
              message="Setup Partially Complete — Manual Steps Required"
              description={
                <div>
                  <Paragraph>
                    Site and resources were created, but credentials could not be auto-written to .env.
                  </Paragraph>
                  <pre style={{ background: 'rgba(0,0,0,0.1)', padding: 12, borderRadius: 6, fontSize: 12, overflow: 'auto' }}>
                    {setupResult.manualInstructions.slice(1).join('\n')}
                  </pre>
                  <Paragraph style={{ marginTop: 12 }}>After updating .env:</Paragraph>
                  <Popconfirm
                    title="Restart Newt container?"
                    description="This will briefly drop all tunnel connections."
                    onConfirm={handleRestartNewt}
                  >
                    <Button type="primary" icon={<SyncOutlined />} loading={restartLoading}>
                      Restart Newt Container
                    </Button>
                  </Popconfirm>
                </div>
              }
            />
          ) : (
            <Alert
              type="success"
              showIcon
              message="Setup Complete"
              description={`Site ${setupResult.site?.siteId} created with ${setupResult.resources?.created || 0} resources.`}
            />
          )}
        </Card>
      )}

      {/* Tunnel Management — shown when fully configured */}
      {isConfigured && config?.siteId && (
        <Card
          title="Tunnel Management"
          extra={
            <Space>
              <Button
                icon={<ReloadOutlined />}
                loading={statusLoading}
                onClick={fetchResourceStatus}
              >
                Refresh
              </Button>
              <Button
                type="primary"
                icon={<SyncOutlined />}
                loading={actionLoading}
                onClick={handleSync}
              >
                Sync Resources
              </Button>
              <Popconfirm
                title="Restart Newt container?"
                description="This will briefly drop all tunnel connections."
                onConfirm={handleRestartNewt}
              >
                <Button
                  danger
                  icon={<PoweroffOutlined />}
                  loading={restartLoading}
                >
                  Restart Newt
                </Button>
              </Popconfirm>
            </Space>
          }
        >
          {/* Summary badges */}
          {resourceStatus && (
            <Space style={{ marginBottom: 16 }} wrap>
              <Tag color="success" style={{ fontSize: 13, padding: '2px 10px' }}>
                <CheckCircleOutlined /> {resourceStatus.summary.healthy} Healthy
              </Tag>
              {resourceStatus.summary.misconfigured > 0 && (
                <Tag color="warning" style={{ fontSize: 13, padding: '2px 10px' }}>
                  <ExclamationCircleOutlined /> {resourceStatus.summary.misconfigured} Issues
                </Tag>
              )}
              {resourceStatus.summary.missing > 0 && (
                <Tag color="error" style={{ fontSize: 13, padding: '2px 10px' }}>
                  <CloseCircleOutlined /> {resourceStatus.summary.missing} Missing
                </Tag>
              )}
              {resourceStatus.summary.extras > 0 && (
                <Tag color="default" style={{ fontSize: 13, padding: '2px 10px' }}>
                  {resourceStatus.summary.extras} Unmanaged
                </Tag>
              )}
            </Space>
          )}

          {/* Sync result alert */}
          {syncResult && (
            <Alert
              type={syncResult.errors > 0 ? 'warning' : 'success'}
              showIcon
              closable
              onClose={() => setSyncResult(null)}
              message={`Sync: ${syncResult.created} created, ${syncResult.targetFixed} targets fixed, ${syncResult.skipped} unchanged`}
              description={syncResult.details.errors.length > 0 ? (
                <ul style={{ margin: '4px 0 0', paddingLeft: 20 }}>
                  {syncResult.details.errors.map((e, i) => <li key={i}>{e}</li>)}
                </ul>
              ) : undefined}
              style={{ marginBottom: 16 }}
            />
          )}

          {/* Live resources table */}
          {statusLoading && !resourceStatus ? (
            <Spin style={{ display: 'block', margin: '24px auto' }} />
          ) : (
            <Table<ResourceStatusItem>
              dataSource={resourceStatus?.resources || []}
              rowKey="fullDomain"
              size="small"
              pagination={false}
              loading={statusLoading}
              columns={[
                {
                  title: 'Service',
                  dataIndex: 'name',
                  key: 'name',
                  render: (name: string, record) => (
                    <Space>
                      <Text strong>{name}</Text>
                      {record.required && <Tag color="red" style={{ fontSize: 11 }}>Required</Tag>}
                    </Space>
                  ),
                },
                {
                  title: 'Domain',
                  dataIndex: 'fullDomain',
                  key: 'fullDomain',
                  ellipsis: true,
                  render: (domain: string) => <Text code copyable={{ text: domain }}>{domain}</Text>,
                },
                {
                  title: 'Status',
                  key: 'status',
                  width: 120,
                  render: (_: unknown, record) => {
                    if (!record.exists) {
                      return <Tag color="error">Missing</Tag>;
                    }
                    if (!record.hasTarget) {
                      return <Tag color="warning">No Target</Tag>;
                    }
                    if (!record.targetCorrect) {
                      return (
                        <Tooltip title={`Expected ${record.expectedTargetIp}:${record.expectedTargetPort}, got ${record.actualTargetIp}:${record.actualTargetPort}`}>
                          <Tag color="warning">Mismatch</Tag>
                        </Tooltip>
                      );
                    }
                    return <Tag color="success">OK</Tag>;
                  },
                },
                {
                  title: 'Target',
                  key: 'target',
                  render: (_: unknown, record) => {
                    if (!record.exists || !record.hasTarget) return <Text type="secondary">—</Text>;
                    const actual = `${record.actualTargetIp}:${record.actualTargetPort}`;
                    if (!record.targetCorrect) {
                      return (
                        <Tooltip title={`Expected: ${record.expectedTargetIp}:${record.expectedTargetPort}`}>
                          <Text code type="warning">{actual}</Text>
                        </Tooltip>
                      );
                    }
                    return <Text code>{actual}</Text>;
                  },
                },
                ...(!isMobile ? [{
                  title: 'Auth',
                  key: 'auth',
                  width: 80,
                  render: (_: unknown, record: ResourceStatusItem) => {
                    if (!record.exists) return null;
                    return record.blockAccess
                      ? <Tag color="orange">SSO</Tag>
                      : <Tag color="green">Public</Tag>;
                  },
                }] : []),
              ]}
            />
          )}

          {/* Unmanaged resources (extras in Pangolin not in YAML) */}
          {resourceStatus && resourceStatus.extras.length > 0 && (
            <Collapse
              style={{ marginTop: 16 }}
              items={[{
                key: 'extras',
                label: `${resourceStatus.extras.length} Unmanaged Resource${resourceStatus.extras.length > 1 ? 's' : ''} (not in YAML)`,
                children: (
                  <Table<ResourceStatusItem>
                    dataSource={resourceStatus.extras}
                    rowKey="fullDomain"
                    size="small"
                    pagination={false}
                    columns={[
                      { title: 'Name', dataIndex: 'name', key: 'name' },
                      {
                        title: 'Domain',
                        dataIndex: 'fullDomain',
                        key: 'fullDomain',
                        render: (d: string) => <Text code>{d}</Text>,
                      },
                      {
                        title: 'Target',
                        key: 'target',
                        render: (_: unknown, r) => r.hasTarget
                          ? <Text code>{r.actualTargetIp}:{r.actualTargetPort}</Text>
                          : <Text type="secondary">—</Text>,
                      },
                    ]}
                  />
                ),
              }]}
            />
          )}
        </Card>
      )}

      {/* Edit Resource Drawer */}
      <Drawer
        title="Edit Resource"
        open={editDrawerOpen}
        destroyOnHidden
        mask={false}
        width={isMobile ? '100%' : 600}
        rootStyle={{ position: 'absolute', top: 64, height: 'calc(100vh - 64px)' }}
        onClose={() => {
          setEditDrawerOpen(false);
          setEditingResource(null);
          editForm.resetFields();
        }}
        extra={
          <Space>
            <Button onClick={() => { setEditDrawerOpen(false); setEditingResource(null); editForm.resetFields(); }}>
              Cancel
            </Button>
            <Button type="primary" loading={actionLoading} onClick={() => editForm.submit()}>
              Update
            </Button>
          </Space>
        }
      >
        <Form form={editForm} layout="vertical" onFinish={handleUpdateResource}>
          <Form.Item label="Name" name="name" rules={[{ required: true }]}>
            <Input />
          </Form.Item>
          <Form.Item label="Protocol" name="protocol">
            <Input placeholder="http" />
          </Form.Item>
          <Form.Item label="Proxy Port" name="proxyPort">
            <Input type="number" placeholder="80" />
          </Form.Item>
          <Form.Item name="ssl" valuePropName="checked">
            <Checkbox>Enable SSL</Checkbox>
          </Form.Item>
          <Form.Item name="active" valuePropName="checked">
            <Checkbox>Active</Checkbox>
          </Form.Item>
          <Form.Item name="blockAccess" valuePropName="checked">
            <Checkbox>Block Access</Checkbox>
          </Form.Item>
        </Form>
      </Drawer>
    </Space>
  );
}
