import { createSignal, onMount, Show, For } from 'solid-js';
import { Button } from './ui/Button';
import { getApiOrigin } from '@/lib/api-url';

interface TOTPSetupResponse {
  secret: string;
  qr_code: string;
  backup_codes: string[];
}

interface TOTPStatus {
  enabled: boolean;
  setup: boolean;
}

export function TwoFactorAuth() {
  const [totpStatus, setTotpStatus] = createSignal<TOTPStatus | null>(null);
  const [setupData, setSetupData] = createSignal<TOTPSetupResponse | null>(null);
  const [loading, setLoading] = createSignal(false);
  const [error, setError] = createSignal<string | null>(null);
  const [success, setSuccess] = createSignal<string | null>(null);

  // Form states
  const [setupPassword, setSetupPassword] = createSignal('');
  const [verifyCode, setVerifyCode] = createSignal('');
  const [enableCode, setEnableCode] = createSignal('');
  const [disableCode, setDisableCode] = createSignal('');
  const [disablePassword, setDisablePassword] = createSignal('');
  const [backupCodeVerify, setBackupCodeVerify] = createSignal('');
  const [regenerateCode, setRegenerateCode] = createSignal('');

  // UI states
  const [showSetup, setShowSetup] = createSignal(false);
  const [backupCodes, setBackupCodes] = createSignal<string[]>([]);

  const getAuthHeaders = () => {
    const token = localStorage.getItem('token');
    return {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json',
    };
  };

  const fetchTOTPStatus = async () => {
    try {
      const response = await fetch(`${getApiOrigin()}/api/v1/auth/2fa/status`, {
        headers: getAuthHeaders(),
      });
      
      if (response.ok) {
        const data = await response.json();
        setTotpStatus(data);
      }
    } catch (err) {
      setError('Failed to fetch 2FA status');
    }
  };

  const setupTOTP = async () => {
    if (!setupPassword()) {
      setError('Password is required');
      return;
    }

    setLoading(true);
    setError(null);
    setSuccess(null);

    try {
      const response = await fetch(`${getApiOrigin()}/api/v1/auth/2fa/setup`, {
        method: 'POST',
        headers: getAuthHeaders(),
        body: JSON.stringify({
          password: setupPassword(),
        }),
      });

      if (response.ok) {
        const data = await response.json();
        setSetupData(data);
        setBackupCodes(data.backup_codes);
        setShowSetup(true);
        setSuccess('TOTP setup initiated. Please scan the QR code and save your backup codes.');
        setSetupPassword('');
      } else {
        const errorData = await response.json();
        setError(errorData.error || 'Failed to setup TOTP');
      }
    } catch (err) {
      setError('Network error. Please try again.');
    } finally {
      setLoading(false);
    }
  };

  const verifyTOTPCode = async () => {
    if (!verifyCode()) {
      setError('Verification code is required');
      return;
    }

    setLoading(true);
    setError(null);

    try {
      const response = await fetch(`${getApiOrigin()}/api/v1/auth/2fa/verify`, {
        method: 'POST',
        headers: getAuthHeaders(),
        body: JSON.stringify({
          code: verifyCode(),
        }),
      });

      if (response.ok) {
        setSuccess('TOTP code verified successfully!');
        setVerifyCode('');
      } else {
        const errorData = await response.json();
        setError(errorData.error || 'Invalid verification code');
      }
    } catch (err) {
      setError('Network error. Please try again.');
    } finally {
      setLoading(false);
    }
  };

  const enableTOTP = async () => {
    if (!enableCode()) {
      setError('Enable code is required');
      return;
    }

    setLoading(true);
    setError(null);
    setSuccess(null);

    try {
      const response = await fetch(`${getApiOrigin()}/api/v1/auth/2fa/enable`, {
        method: 'POST',
        headers: getAuthHeaders(),
        body: JSON.stringify({
          code: enableCode(),
        }),
      });

      if (response.ok) {
        setSuccess('Two-Factor Authentication enabled successfully!');
        setEnableCode('');
        setShowSetup(false);
        setSetupData(null);
        await fetchTOTPStatus();
      } else {
        const errorData = await response.json();
        setError(errorData.error || 'Failed to enable TOTP');
      }
    } catch (err) {
      setError('Network error. Please try again.');
    } finally {
      setLoading(false);
    }
  };

  const disableTOTP = async () => {
    if (!disableCode() || !disablePassword()) {
      setError('Both code and password are required');
      return;
    }

    setLoading(true);
    setError(null);
    setSuccess(null);

    try {
      const response = await fetch(`${getApiOrigin()}/api/v1/auth/2fa/disable`, {
        method: 'POST',
        headers: getAuthHeaders(),
        body: JSON.stringify({
          code: disableCode(),
          password: disablePassword(),
        }),
      });

      if (response.ok) {
        setSuccess('Two-Factor Authentication disabled successfully!');
        setDisableCode('');
        setDisablePassword('');
        await fetchTOTPStatus();
      } else {
        const errorData = await response.json();
        setError(errorData.error || 'Failed to disable TOTP');
      }
    } catch (err) {
      setError('Network error. Please try again.');
    } finally {
      setLoading(false);
    }
  };

  const verifyBackupCode = async () => {
    if (!backupCodeVerify()) {
      setError('Backup code is required');
      return;
    }

    setLoading(true);
    setError(null);

    try {
      const response = await fetch(`${getApiOrigin()}/api/v1/auth/2fa/backup-codes/verify`, {
        method: 'POST',
        headers: getAuthHeaders(),
        body: JSON.stringify({
          code: backupCodeVerify(),
        }),
      });

      if (response.ok) {
        const data = await response.json();
        setSuccess(`Backup code verified! ${data.remaining_codes} codes remaining.`);
        setBackupCodeVerify('');
      } else {
        const errorData = await response.json();
        setError(errorData.error || 'Invalid backup code');
      }
    } catch (err) {
      setError('Network error. Please try again.');
    } finally {
      setLoading(false);
    }
  };

  const regenerateBackupCodes = async () => {
    if (!regenerateCode()) {
      setError('Current TOTP code is required');
      return;
    }

    setLoading(true);
    setError(null);
    setSuccess(null);

    try {
      const response = await fetch(`${getApiOrigin()}/api/v1/auth/2fa/backup-codes/regenerate`, {
        method: 'POST',
        headers: getAuthHeaders(),
        body: JSON.stringify({
          code: regenerateCode(),
        }),
      });

      if (response.ok) {
        const data = await response.json();
        setBackupCodes(data.backup_codes);
        setSuccess('Backup codes regenerated successfully!');
        setRegenerateCode('');
      } else {
        const errorData = await response.json();
        setError(errorData.error || 'Failed to regenerate backup codes');
      }
    } catch (err) {
      setError('Network error. Please try again.');
    } finally {
      setLoading(false);
    }
  };

  onMount(() => {
    fetchTOTPStatus();
  });

  return (
    <div class="space-y-6">
      <div class="flex items-center justify-between">
        <h2 class="text-2xl font-bold text-foreground">Two-Factor Authentication</h2>
        <div class="flex items-center space-x-2">
          <div class={`w-3 h-3 rounded-full ${totpStatus()?.enabled ? 'bg-primary' : 'bg-muted'}`}></div>
          <span class="text-muted-foreground">
            {totpStatus()?.enabled ? 'Enabled' : 'Disabled'}
          </span>
        </div>
      </div>

      {/* Error and Success Messages */}
      <Show when={error()}>
        <div class="bg-destructive/15 border border-destructive/20 text-destructive px-4 py-3 rounded-lg">
          {error()}
        </div>
      </Show>

      <Show when={success()}>
        <div class="bg-primary/15 border border-primary/20 text-primary px-4 py-3 rounded-lg">
          {success()}
        </div>
      </Show>

      {/* Current Status */}
      <div class="border rounded-lg p-6">
        <h3 class="text-lg font-semibold text-foreground mb-4">Current Status</h3>
        <div class="space-y-2">
          <div class="flex justify-between items-center">
            <span class="text-muted-foreground">2FA Status:</span>
            <span class={`font-medium ${totpStatus()?.enabled ? 'text-primary' : 'text-muted-foreground'}`}>
              {totpStatus()?.enabled ? 'Enabled' : 'Disabled'}
            </span>
          </div>
          <div class="flex justify-between items-center">
            <span class="text-muted-foreground">Setup Status:</span>
            <span class={`font-medium ${totpStatus()?.setup ? 'text-blue-500' : 'text-muted-foreground'}`}>
              {totpStatus()?.setup ? 'Configured' : 'Not Configured'}
            </span>
          </div>
        </div>
      </div>

      {/* Setup TOTP */}
      <Show when={!totpStatus()?.enabled}>
        <div class="border rounded-lg p-6">
          <h3 class="text-lg font-semibold text-foreground mb-4">Setup Two-Factor Authentication</h3>
          <p class="text-muted-foreground mb-4">
            Enable 2FA to add an extra layer of security to your account. You'll need a TOTP app like Google Authenticator or Authy.
          </p>
          
          <div class="space-y-4">
            <div>
              <label class="block text-sm font-medium text-muted-foreground mb-2">
                Confirm Password
              </label>
              <input
                type="password"
                value={setupPassword()}
                onInput={(e) => setSetupPassword(e.currentTarget.value)}
                class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground focus-visible:outline-none focus-visible:ring-1.5 focus-visible:ring-ring"
                placeholder="Enter your password"
              />
            </div>
            
            <Button
              onClick={setupTOTP}
              disabled={loading()}
              class="w-full"
            >
              {loading() ? 'Setting up...' : 'Setup 2FA'}
            </Button>
          </div>
        </div>
      </Show>

      {/* TOTP Setup Process */}
      <Show when={showSetup() && setupData()}>
        <div class="border rounded-lg p-6">
          <h3 class="text-lg font-semibold text-foreground mb-4">Complete 2FA Setup</h3>
          
          <div class="space-y-6">
            {/* QR Code */}
            <div class="text-center">
              <h4 class="text-md font-medium text-foreground mb-3">Scan QR Code</h4>
              <img 
                src={setupData()!.qr_code} 
                alt="TOTP QR Code"
                class="mx-auto border-2 border-border rounded-lg"
              />
              <p class="text-sm text-muted-foreground mt-2">
                Or manually enter this secret in your TOTP app:
              </p>
              <code class="block bg-muted px-3 py-2 rounded text-primary break-all">
                {setupData()!.secret}
              </code>
            </div>

            {/* Backup Codes */}
            <div>
              <h4 class="text-md font-medium text-foreground mb-3">Backup Codes</h4>
              <p class="text-sm text-muted-foreground mb-3">
                Save these backup codes in a secure location. You can use them to access your account if you lose your TOTP device.
              </p>
              <div class="grid grid-cols-2 gap-2">
                <For each={backupCodes()}>
                  {(code) => (
                    <code class="bg-muted px-3 py-2 rounded text-foreground text-sm">
                      {code}
                    </code>
                  )}
                </For>
              </div>
            </div>

            {/* Verification */}
            <div>
              <h4 class="text-md font-medium text-foreground mb-3">Verify Setup</h4>
              <div class="space-y-4">
                <div>
                  <label class="block text-sm font-medium text-muted-foreground mb-2">
                    Enter 6-digit code
                  </label>
                  <input
                    type="text"
                    value={verifyCode()}
                    onInput={(e) => setVerifyCode(e.currentTarget.value.replace(/\D/g, '').slice(0, 6))}
                    class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground focus-visible:outline-none focus-visible:ring-1.5 focus-visible:ring-ring"
                    placeholder="000000"
                    maxlength={6}
                  />
                </div>
                
                <div class="flex space-x-3">
                  <Button
                    onClick={verifyTOTPCode}
                    disabled={loading() || verifyCode().length !== 6}
                    class="flex-1"
                  >
                    {loading() ? 'Verifying...' : 'Verify Code'}
                  </Button>
                  
                  <Button
                    onClick={enableTOTP}
                    disabled={loading() || verifyCode().length !== 6}
                    variant="secondary"
                    class="flex-1"
                  >
                    {loading() ? 'Enabling...' : 'Enable 2FA'}
                  </Button>
                </div>
              </div>
            </div>
          </div>
        </div>
      </Show>

      {/* Disable 2FA */}
      <Show when={totpStatus()?.enabled}>
        <div class="border rounded-lg p-6">
          <h3 class="text-lg font-semibold text-foreground mb-4">Disable Two-Factor Authentication</h3>
          <p class="text-muted-foreground mb-4">
            Disabling 2FA will make your account less secure. You'll need to provide your current TOTP code and password.
          </p>
          
          <div class="space-y-4">
            <div>
              <label class="block text-sm font-medium text-muted-foreground mb-2">
                TOTP Code
              </label>
              <input
                type="text"
                value={disableCode()}
                onInput={(e) => setDisableCode(e.currentTarget.value.replace(/\D/g, '').slice(0, 6))}
                class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground focus-visible:outline-none focus-visible:ring-1.5 focus-visible:ring-ring"
                placeholder="000000"
                maxlength={6}
              />
            </div>
            
            <div>
              <label class="block text-sm font-medium text-muted-foreground mb-2">
                Password
              </label>
              <input
                type="password"
                value={disablePassword()}
                onInput={(e) => setDisablePassword(e.currentTarget.value)}
                class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground focus-visible:outline-none focus-visible:ring-1.5 focus-visible:ring-ring"
                placeholder="Enter your password"
              />
            </div>
            
            <Button
              onClick={disableTOTP}
              disabled={loading()}
              variant="destructive"
              class="w-full"
            >
              {loading() ? 'Disabling...' : 'Disable 2FA'}
            </Button>
          </div>
        </div>
      </Show>

      {/* Backup Code Management */}
      <Show when={totpStatus()?.enabled}>
        <div class="border rounded-lg p-6">
          <h3 class="text-lg font-semibold text-foreground mb-4">Backup Code Management</h3>
          
          <div class="space-y-6">
            {/* Verify Backup Code */}
            <div>
              <h4 class="text-md font-medium text-foreground mb-3">Verify Backup Code</h4>
              <div class="space-y-4">
                <input
                  type="text"
                  value={backupCodeVerify()}
                  onInput={(e) => setBackupCodeVerify(e.currentTarget.value)}
                  class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground focus-visible:outline-none focus-visible:ring-1.5 focus-visible:ring-ring"
                  placeholder="Enter backup code"
                />
                
                <Button
                  onClick={verifyBackupCode}
                  disabled={loading()}
                  class="w-full"
                >
                  {loading() ? 'Verifying...' : 'Verify Backup Code'}
                </Button>
              </div>
            </div>

            {/* Regenerate Backup Codes */}
            <div>
              <h4 class="text-md font-medium text-foreground mb-3">Regenerate Backup Codes</h4>
              <p class="text-sm text-muted-foreground mb-3">
                This will invalidate all existing backup codes and generate new ones.
              </p>
              
              <div class="space-y-4">
                <input
                  type="text"
                  value={regenerateCode()}
                  onInput={(e) => setRegenerateCode(e.currentTarget.value.replace(/\D/g, '').slice(0, 6))}
                  class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground focus-visible:outline-none focus-visible:ring-1.5 focus-visible:ring-ring"
                  placeholder="Current TOTP code"
                  maxlength={6}
                />
                
                <Button
                  onClick={regenerateBackupCodes}
                  disabled={loading()}
                  variant="secondary"
                  class="w-full"
                >
                  {loading() ? 'Regenerating...' : 'Regenerate Backup Codes'}
                </Button>
              </div>
            </div>

            {/* Show New Backup Codes */}
            <Show when={backupCodes().length > 0}>
              <div>
                <h4 class="text-md font-medium text-foreground mb-3">New Backup Codes</h4>
                <p class="text-sm text-muted-foreground mb-3">
                  Save these new backup codes in a secure location:
                </p>
                <div class="grid grid-cols-2 gap-2">
                  <For each={backupCodes()}>
                    {(code) => (
                      <code class="bg-muted px-3 py-2 rounded text-foreground text-sm">
                        {code}
                      </code>
                    )}
                  </For>
                </div>
              </div>
            </Show>
          </div>
        </div>
      </Show>
    </div>
  );
}
