import { useEffect, useState } from 'react';
import { Eye, EyeOff } from 'lucide-react';
import {
  Button, Input, Toggle, FormField, SectionHeader, Tag, ConfirmDialog,
} from '@cameleer/design-system';
import { useToast } from '@cameleer/design-system';
import { PageLoader } from '../../components/PageLoader';
import { adminFetch } from '../../api/queries/admin/admin-api';
import ClaimMappingRulesModal from './ClaimMappingRulesModal';
import { useClaimMappingRules } from '../../api/queries/admin/claim-mappings';
import { describeApiError } from '../../api/errors';
import styles from './OidcConfigPage.module.css';
import sectionStyles from '../../styles/section-card.module.css';

interface OidcFormData {
  enabled: boolean;
  autoSignup: boolean;
  issuerUri: string;
  clientId: string;
  clientSecret: string;
  rolesClaim: string;
  displayNameClaim: string;
  userIdClaim: string;
  defaultRoles: string[];
  audience: string;
  additionalScopes: string[];
}

// Platform-managed scopes — always requested by the auth flow, hidden from the admin UI
const PLATFORM_SCOPES = new Set(['urn:logto:scope:organizations', 'urn:logto:scope:organization_roles']);

const EMPTY_CONFIG: OidcFormData = {
  enabled: false,
  autoSignup: true,
  issuerUri: '',
  clientId: '',
  clientSecret: '',
  rolesClaim: 'roles',
  displayNameClaim: 'name',
  userIdClaim: 'sub',
  defaultRoles: ['VIEWER'],
  audience: '',
  additionalScopes: [],
};

export default function OidcConfigPage() {
  const [form, setForm] = useState<OidcFormData | null>(null);
  const [editing, setEditing] = useState(false);
  const [formDraft, setFormDraft] = useState<OidcFormData | null>(null);
  const [newRole, setNewRole] = useState('');
  const [showSecret, setShowSecret] = useState(false);
  const [deleteOpen, setDeleteOpen] = useState(false);
  const [saving, setSaving] = useState(false);
  const [testing, setTesting] = useState(false);
  const { toast } = useToast();
  const [rulesModalOpen, setRulesModalOpen] = useState(false);
  const { data: claimRules = [] } = useClaimMappingRules();

  useEffect(() => {
    adminFetch<Partial<OidcFormData> & { configured?: boolean }>('/oidc')
      .then((data) => setForm({
        enabled: data.enabled ?? false,
        autoSignup: data.autoSignup ?? true,
        issuerUri: data.issuerUri ?? '',
        clientId: data.clientId ?? '',
        clientSecret: data.clientSecret ?? '',
        rolesClaim: data.rolesClaim ?? 'roles',
        displayNameClaim: data.displayNameClaim ?? 'name',
        userIdClaim: data.userIdClaim ?? 'sub',
        defaultRoles: data.defaultRoles ?? ['VIEWER'],
        audience: (data as any).audience ?? '',
        additionalScopes: ((data as any).additionalScopes ?? []).filter((s: string) => !PLATFORM_SCOPES.has(s)),
      }))
      .catch(() => setForm(EMPTY_CONFIG));
  }, []);

  // The display values come from formDraft when editing, form otherwise
  const current = editing ? formDraft : form;

  function startEditing() {
    setFormDraft(form ? { ...form } : null);
    setEditing(true);
  }

  function cancelEditing() {
    setFormDraft(null);
    setEditing(false);
    setNewRole('');
  }

  function updateDraft<K extends keyof OidcFormData>(key: K, value: OidcFormData[K]) {
    setFormDraft((prev) => prev ? { ...prev, [key]: value } : prev);
  }

  function addRole() {
    if (!current) return;
    const role = newRole.trim().toUpperCase();
    if (role && !(current.defaultRoles || []).includes(role)) {
      updateDraft('defaultRoles', [...(current.defaultRoles || []), role]);
      setNewRole('');
    }
  }

  function removeRole(role: string) {
    if (!current) return;
    updateDraft('defaultRoles', (current.defaultRoles || []).filter((r) => r !== role));
  }

  async function handleSave() {
    if (!formDraft) return;
    setSaving(true);
    try {
      await adminFetch('/oidc', { method: 'PUT', body: JSON.stringify(formDraft) });
      setForm({ ...formDraft });
      setFormDraft(null);
      setEditing(false);
      toast({ title: 'Settings saved', description: 'OIDC configuration updated successfully.', variant: 'success' });
    } catch (e) {
      toast({ title: 'Failed to save OIDC configuration', description: describeApiError(e), variant: 'error', duration: 86_400_000 });
    } finally {
      setSaving(false);
    }
  }

  async function handleTest() {
    if (!form) return;
    setTesting(true);
    try {
      const result = await adminFetch<{ status: string; authorizationEndpoint?: string }>('/oidc/test', { method: 'POST' });
      toast({ title: 'Connection test', description: `OIDC provider responded: ${result.status}`, variant: 'success' });
    } catch (e) {
      toast({ title: 'Connection test failed', description: describeApiError(e), variant: 'error', duration: 86_400_000 });
    } finally {
      setTesting(false);
    }
  }

  async function handleDelete() {
    setDeleteOpen(false);
    try {
      await adminFetch('/oidc', { method: 'DELETE' });
      setForm(EMPTY_CONFIG);
      setFormDraft(null);
      setEditing(false);
      toast({ title: 'Configuration deleted', description: 'OIDC configuration has been removed.', variant: 'warning' });
    } catch (e) {
      toast({ title: 'Failed to delete OIDC configuration', description: describeApiError(e), variant: 'error', duration: 86_400_000 });
    }
  }

  if (!form) return <PageLoader />;

  return (
    <div className={styles.page}>
      <div className={styles.toolbar}>
        {editing ? (
          <>
            <Button size="sm" variant="ghost" onClick={cancelEditing}>Cancel</Button>
            <Button size="sm" variant="primary" onClick={handleSave} loading={saving}>Save</Button>
          </>
        ) : (
          <>
            <Button size="sm" variant="secondary" onClick={handleTest} disabled={!form.issuerUri || testing}>
              {testing ? 'Testing...' : 'Test Connection'}
            </Button>
            <Button size="sm" variant="secondary" onClick={startEditing}>Edit</Button>
          </>
        )}
      </div>

      <section className={sectionStyles.section}>
        <SectionHeader>Behavior</SectionHeader>
        <div className={styles.toggleRow}>
          <Toggle
            label="Enabled"
            checked={current?.enabled ?? false}
            onChange={(e) => updateDraft('enabled', e.target.checked)}
            disabled={!editing}
          />
        </div>
        <div className={styles.toggleRow}>
          <Toggle
            label="Auto Sign-Up"
            checked={current?.autoSignup ?? true}
            onChange={(e) => updateDraft('autoSignup', e.target.checked)}
            disabled={!editing}
          />
          <span className={styles.hint}>Automatically create accounts for new OIDC users</span>
        </div>
      </section>

      <section className={sectionStyles.section}>
        <SectionHeader>Provider Settings</SectionHeader>
        <FormField label="Issuer URI" htmlFor="issuer">
          <Input
            id="issuer"
            type="url"
            placeholder="https://idp.example.com/realms/my-realm"
            value={current?.issuerUri ?? ''}
            onChange={(e) => updateDraft('issuerUri', e.target.value)}
            disabled={!editing}
          />
        </FormField>
        <FormField label="Client ID" htmlFor="client-id">
          <Input
            id="client-id"
            value={current?.clientId ?? ''}
            onChange={(e) => updateDraft('clientId', e.target.value)}
            disabled={!editing}
          />
        </FormField>
        <FormField label="Client Secret" htmlFor="client-secret">
          <div style={{ position: 'relative' }}>
            <Input
              id="client-secret"
              type={showSecret ? 'text' : 'password'}
              value={current?.clientSecret ?? ''}
              onChange={(e) => updateDraft('clientSecret', e.target.value)}
              disabled={!editing}
            />
            {editing && (
              <Button
                variant="ghost"
                size="sm"
                style={{ position: 'absolute', right: 4, top: '50%', transform: 'translateY(-50%)' }}
                onClick={() => setShowSecret(!showSecret)}
              >
                {showSecret ? <EyeOff size={14} /> : <Eye size={14} />}
              </Button>
            )}
          </div>
        </FormField>
        <FormField label="Audience / API Resource" htmlFor="audience" hint="RFC 8707 resource indicator sent in the authorization request">
          <Input
            id="audience"
            placeholder="https://api.example.com"
            value={current?.audience ?? ''}
            onChange={(e) => updateDraft('audience', e.target.value)}
            disabled={!editing}
          />
        </FormField>
        <FormField label="Additional Scopes" htmlFor="additional-scopes" hint="Extra scopes to request beyond openid email profile (comma-separated)">
          <Input
            id="additional-scopes"
            placeholder="urn:scope:organizations, urn:scope:roles"
            value={(current?.additionalScopes || []).join(', ')}
            onChange={(e) => updateDraft('additionalScopes', e.target.value.split(',').map(s => s.trim()).filter(Boolean))}
            disabled={!editing}
          />
        </FormField>
      </section>

      <section className={sectionStyles.section}>
        <SectionHeader>Claim Mapping</SectionHeader>
        <FormField label="Roles Claim" htmlFor="roles-claim" hint="JSON path to roles in the access token or ID token">
          <Input
            id="roles-claim"
            value={current?.rolesClaim ?? ''}
            onChange={(e) => updateDraft('rolesClaim', e.target.value)}
            disabled={!editing}
          />
        </FormField>
        <FormField label="User ID Claim" htmlFor="userid-claim" hint="Claim used as unique user identifier (default: sub)">
          <Input
            id="userid-claim"
            value={current?.userIdClaim ?? ''}
            onChange={(e) => updateDraft('userIdClaim', e.target.value)}
            disabled={!editing}
          />
        </FormField>
        <FormField label="Display Name Claim" htmlFor="name-claim" hint="Claim used for user display name">
          <Input
            id="name-claim"
            value={current?.displayNameClaim ?? ''}
            onChange={(e) => updateDraft('displayNameClaim', e.target.value)}
            disabled={!editing}
          />
        </FormField>
        <div className={styles.advancedRulesRow}>
          <div className={styles.advancedRulesInner}>
            <div>
              <span className={styles.advancedRulesLabel}>Advanced Rules</span>
              {claimRules.length > 0 && (
                <span className={styles.advancedRulesCount}>
                  {claimRules.length} active rule{claimRules.length !== 1 ? 's' : ''}
                </span>
              )}
            </div>
            <Button size="sm" variant="secondary" onClick={() => setRulesModalOpen(true)}>
              Edit Rules
            </Button>
          </div>
        </div>
        <ClaimMappingRulesModal open={rulesModalOpen} onClose={() => setRulesModalOpen(false)} />
      </section>

      <section className={sectionStyles.section}>
        <SectionHeader>Default Roles</SectionHeader>
        <div className={styles.tagList}>
          {(current?.defaultRoles || []).map((role) => (
            <Tag key={role} label={role} color="primary" onRemove={editing ? () => removeRole(role) : undefined} />
          ))}
          {(current?.defaultRoles || []).length === 0 && (
            <span className={styles.noRoles}>No default roles configured</span>
          )}
        </div>
        {editing && (
          <div className={styles.addRoleRow}>
            <Input
              placeholder="Add role..."
              value={newRole}
              onChange={(e) => setNewRole(e.target.value)}
              onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); addRole(); } }}
              className={styles.roleInput}
            />
            <Button size="sm" variant="secondary" onClick={addRole} disabled={!newRole.trim()}>
              Add
            </Button>
          </div>
        )}
      </section>

      <section className={sectionStyles.section}>
        <SectionHeader>Danger Zone</SectionHeader>
        <Button size="sm" variant="danger" onClick={() => setDeleteOpen(true)}>
          Delete OIDC Configuration
        </Button>
        <ConfirmDialog
          open={deleteOpen}
          onClose={() => setDeleteOpen(false)}
          onConfirm={handleDelete}
          message="Delete OIDC configuration? All users signed in via OIDC will lose access."
          confirmText="delete oidc"
          loading={saving}
        />
      </section>
    </div>
  );
}
