'use client';

import { useState, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { apiClient } from '@/infrastructure/api/api-client';
import { queryKeys } from '@/infrastructure/api/query-keys';
import { cn } from '@/lib/utils';

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

interface RiskRule {
  id: string;
  pattern: string;
  riskLevel: 0 | 1 | 2 | 3;
  action: 'allow' | 'block' | 'require_approval';
  description: string;
}

interface RiskRuleFormData {
  pattern: string;
  riskLevel: 0 | 1 | 2 | 3;
  action: 'allow' | 'block' | 'require_approval';
  description: string;
}

type RiskRulesResponse = RiskRule[];

type Role = 'admin' | 'operator' | 'viewer' | 'readonly';
type Permission =
  | 'manage_servers'
  | 'execute_commands'
  | 'view_audit'
  | 'manage_users'
  | 'approve_commands';

type PermissionMatrix = Record<Role, Permission[]>;

// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------

const RISK_LEVELS: { value: RiskRule['riskLevel']; labelKey: string; color: string }[] = [
  { value: 0, labelKey: 'riskRules.riskLevels.0', color: 'bg-gray-100 text-gray-800 dark:bg-gray-800/40 dark:text-gray-300' },
  { value: 1, labelKey: 'riskRules.riskLevels.1', color: 'bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-400' },
  { value: 2, labelKey: 'riskRules.riskLevels.2', color: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400' },
  { value: 3, labelKey: 'riskRules.riskLevels.3', color: 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400' },
];

const ACTIONS: { value: RiskRule['action']; labelKey: string }[] = [
  { value: 'allow', labelKey: 'riskRules.actions.allow' },
  { value: 'block', labelKey: 'riskRules.actions.block' },
  { value: 'require_approval', labelKey: 'riskRules.actions.requireApproval' },
];

const ROLES: { value: Role; labelKey: string }[] = [
  { value: 'admin', labelKey: 'permissionMatrix.roles.admin' },
  { value: 'operator', labelKey: 'permissionMatrix.roles.operator' },
  { value: 'viewer', labelKey: 'permissionMatrix.roles.viewer' },
  { value: 'readonly', labelKey: 'permissionMatrix.roles.readonly' },
];

const PERMISSIONS: { value: Permission; labelKey: string }[] = [
  { value: 'manage_servers', labelKey: 'permissionMatrix.permissions.manageServers' },
  { value: 'execute_commands', labelKey: 'permissionMatrix.permissions.executeCommands' },
  { value: 'view_audit', labelKey: 'permissionMatrix.permissions.viewAudit' },
  { value: 'manage_users', labelKey: 'permissionMatrix.permissions.manageUsers' },
  { value: 'approve_commands', labelKey: 'permissionMatrix.permissions.approveCommands' },
];

const DEFAULT_MATRIX: PermissionMatrix = {
  admin: ['manage_servers', 'execute_commands', 'view_audit', 'manage_users', 'approve_commands'],
  operator: ['execute_commands', 'view_audit'],
  viewer: ['view_audit'],
  readonly: [],
};

const EMPTY_RULE_FORM: RiskRuleFormData = {
  pattern: '',
  riskLevel: 0,
  action: 'allow',
  description: '',
};

// ---------------------------------------------------------------------------
// Risk level badge
// ---------------------------------------------------------------------------

function RiskBadge({ level }: { level: RiskRule['riskLevel'] }) {
  const meta = RISK_LEVELS.find((r) => r.value === level) ?? RISK_LEVELS[0];
  return (
    <span
      className={cn(
        'inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium',
        meta.color,
      )}
    >
      Level {level}
    </span>
  );
}

// ---------------------------------------------------------------------------
// Action badge
// ---------------------------------------------------------------------------

function ActionBadge({ action }: { action: RiskRule['action'] }) {
  const { t } = useTranslation('security');
  const styles: Record<RiskRule['action'], string> = {
    allow: 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400',
    block: 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400',
    require_approval:
      'bg-amber-100 text-amber-800 dark:bg-amber-900/30 dark:text-amber-400',
  };

  const labelKeys: Record<RiskRule['action'], string> = {
    allow: 'riskRules.actions.allow',
    block: 'riskRules.actions.block',
    require_approval: 'riskRules.actions.requireApproval',
  };

  return (
    <span
      className={cn(
        'inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium',
        styles[action],
      )}
    >
      {t(labelKeys[action])}
    </span>
  );
}

// ---------------------------------------------------------------------------
// Rule form dialog
// ---------------------------------------------------------------------------

function RuleDialog({
  open,
  title,
  form,
  errors,
  saving,
  onClose,
  onChange,
  onSubmit,
}: {
  open: boolean;
  title: string;
  form: RiskRuleFormData;
  errors: Partial<Record<keyof RiskRuleFormData, string>>;
  saving: boolean;
  onClose: () => void;
  onChange: (field: keyof RiskRuleFormData, value: string | number) => void;
  onSubmit: () => void;
}) {
  const { t } = useTranslation('security');
  const { t: tc } = useTranslation('common');
  if (!open) return null;

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center">
      <div className="absolute inset-0 bg-black/50" onClick={onClose} />

      <div className="relative z-10 w-full max-w-lg bg-card border rounded-lg shadow-lg p-6 mx-4">
        <h2 className="text-lg font-semibold mb-4">{title}</h2>

        <div className="space-y-4">
          {/* pattern */}
          <div>
            <label className="block text-sm font-medium mb-1">
              {t('riskRules.form.pattern')} <span className="text-destructive">*</span>
            </label>
            <input
              type="text"
              value={form.pattern}
              onChange={(e) => onChange('pattern', e.target.value)}
              className={cn(
                'w-full px-3 py-2 rounded-md border bg-background text-sm font-mono',
                errors.pattern ? 'border-destructive' : 'border-input',
              )}
              placeholder={t('riskRules.form.patternPlaceholder')}
            />
            {errors.pattern && (
              <p className="text-xs text-destructive mt-1">{errors.pattern}</p>
            )}
          </div>

          {/* riskLevel */}
          <div>
            <label className="block text-sm font-medium mb-1">{t('riskRules.form.riskLevel')}</label>
            <select
              value={form.riskLevel}
              onChange={(e) => onChange('riskLevel', parseInt(e.target.value, 10))}
              className="w-full px-3 py-2 rounded-md border border-input bg-background text-sm"
            >
              {RISK_LEVELS.map((rl) => (
                <option key={rl.value} value={rl.value}>
                  {t(rl.labelKey)}
                </option>
              ))}
            </select>
          </div>

          {/* action */}
          <div>
            <label className="block text-sm font-medium mb-1">{t('riskRules.form.action')}</label>
            <select
              value={form.action}
              onChange={(e) => onChange('action', e.target.value)}
              className="w-full px-3 py-2 rounded-md border border-input bg-background text-sm"
            >
              {ACTIONS.map((a) => (
                <option key={a.value} value={a.value}>
                  {t(a.labelKey)}
                </option>
              ))}
            </select>
          </div>

          {/* description */}
          <div>
            <label className="block text-sm font-medium mb-1">{t('riskRules.form.description')}</label>
            <input
              type="text"
              value={form.description}
              onChange={(e) => onChange('description', e.target.value)}
              className="w-full px-3 py-2 rounded-md border border-input bg-background text-sm"
              placeholder="Describe this rule..."
            />
          </div>
        </div>

        <div className="flex justify-end gap-3 mt-6 pt-4 border-t">
          <button
            type="button"
            onClick={onClose}
            className="px-4 py-2 text-sm rounded-md border border-input hover:bg-accent"
            disabled={saving}
          >
            {tc('cancel')}
          </button>
          <button
            type="button"
            onClick={onSubmit}
            disabled={saving}
            className="px-4 py-2 text-sm rounded-md bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-50"
          >
            {saving ? tc('saving') : tc('save')}
          </button>
        </div>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Delete confirmation dialog
// ---------------------------------------------------------------------------

function DeleteRuleDialog({
  open,
  pattern,
  deleting,
  onClose,
  onConfirm,
}: {
  open: boolean;
  pattern: string;
  deleting: boolean;
  onClose: () => void;
  onConfirm: () => void;
}) {
  const { t } = useTranslation('security');
  const { t: tc } = useTranslation('common');
  if (!open) return null;

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center">
      <div className="absolute inset-0 bg-black/50" onClick={onClose} />
      <div className="relative z-10 w-full max-w-sm bg-card border rounded-lg shadow-lg p-6 mx-4">
        <h2 className="text-lg font-semibold mb-2">{t('riskRules.deleteRule')}</h2>
        <p className="text-sm text-muted-foreground mb-6">
          {tc('confirmDelete')}{' '}
          <code className="px-1 py-0.5 rounded bg-muted font-mono text-xs">{pattern}</code>
        </p>
        <div className="flex justify-end gap-3">
          <button
            onClick={onClose}
            className="px-4 py-2 text-sm rounded-md border border-input hover:bg-accent"
            disabled={deleting}
          >
            {tc('cancel')}
          </button>
          <button
            onClick={onConfirm}
            disabled={deleting}
            className="px-4 py-2 text-sm rounded-md bg-destructive text-destructive-foreground hover:bg-destructive/90 disabled:opacity-50"
          >
            {deleting ? tc('deleting') : tc('delete')}
          </button>
        </div>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Permission matrix section
// ---------------------------------------------------------------------------

function PermissionMatrixSection({
  matrix,
  saving,
  onToggle,
  onSave,
}: {
  matrix: PermissionMatrix;
  saving: boolean;
  onToggle: (role: Role, perm: Permission) => void;
  onSave: () => void;
}) {
  const { t } = useTranslation('security');
  const { t: tc } = useTranslation('common');
  return (
    <div className="border rounded-lg p-6">
      <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-4">
        <div>
          <h2 className="text-lg font-semibold">{t('permissionMatrix.title')}</h2>
          <p className="text-sm text-muted-foreground mt-1">
            Configure which roles have access to each permission.
          </p>
        </div>
        <button
          onClick={onSave}
          disabled={saving}
          className="px-4 py-2 text-sm rounded-md bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-50 whitespace-nowrap"
        >
          {saving ? tc('saving') : t('permissionMatrix.savePermissions')}
        </button>
      </div>

      <div className="overflow-x-auto">
        <table className="w-full text-sm">
          <thead>
            <tr className="border-b bg-muted/50">
              <th className="text-left px-4 py-3 font-medium">{tc('role')}</th>
              {PERMISSIONS.map((perm) => (
                <th key={perm.value} className="text-center px-3 py-3 font-medium whitespace-nowrap">
                  {t(perm.labelKey)}
                </th>
              ))}
            </tr>
          </thead>
          <tbody>
            {ROLES.map((role) => (
              <tr
                key={role.value}
                className="border-b last:border-b-0 hover:bg-muted/30 transition-colors"
              >
                <td className="px-4 py-3 font-medium capitalize">{t(role.labelKey)}</td>
                {PERMISSIONS.map((perm) => {
                  const checked = (matrix[role.value] ?? []).includes(perm.value);
                  return (
                    <td key={perm.value} className="text-center px-3 py-3">
                      <input
                        type="checkbox"
                        checked={checked}
                        onChange={() => onToggle(role.value, perm.value)}
                        className="h-4 w-4 rounded border-input text-primary focus:ring-primary cursor-pointer"
                      />
                    </td>
                  );
                })}
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Main page component
// ---------------------------------------------------------------------------

export default function RiskRulesPage() {
  const { t } = useTranslation('security');
  const { t: tc } = useTranslation('common');
  const queryClient = useQueryClient();

  // Risk rules state -----------------------------------------------------
  const [dialogOpen, setDialogOpen] = useState(false);
  const [editingRule, setEditingRule] = useState<RiskRule | null>(null);
  const [deleteTarget, setDeleteTarget] = useState<RiskRule | null>(null);
  const [form, setForm] = useState<RiskRuleFormData>({ ...EMPTY_RULE_FORM });
  const [errors, setErrors] = useState<Partial<Record<keyof RiskRuleFormData, string>>>({});

  // Permission matrix state ----------------------------------------------
  const [matrix, setMatrix] = useState<PermissionMatrix>({ ...DEFAULT_MATRIX });

  // Queries - risk rules -------------------------------------------------
  const {
    data: rulesData,
    isLoading: rulesLoading,
    error: rulesError,
  } = useQuery({
    queryKey: queryKeys.riskRules.list(),
    queryFn: () => apiClient<RiskRulesResponse>('/api/v1/agent/risk-rules'),
  });

  const rules = Array.isArray(rulesData) ? rulesData : [];

  // Queries - permissions matrix -----------------------------------------
  const { isLoading: matrixLoading } = useQuery({
    queryKey: queryKeys.permissions.matrix(),
    queryFn: () => apiClient<PermissionMatrix>('/api/v1/agent/permissions'),
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    select: (data: any) => data,
    placeholderData: DEFAULT_MATRIX,
  });

  // Mutations - risk rules -----------------------------------------------
  const createRuleMutation = useMutation({
    mutationFn: (body: Record<string, unknown>) =>
      apiClient<RiskRule>('/api/v1/agent/risk-rules', { method: 'POST', body }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: queryKeys.riskRules.all });
      closeDialog();
    },
  });

  const updateRuleMutation = useMutation({
    mutationFn: ({ id, body }: { id: string; body: Record<string, unknown> }) =>
      apiClient<RiskRule>(`/api/v1/agent/risk-rules/${id}`, { method: 'PUT', body }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: queryKeys.riskRules.all });
      closeDialog();
    },
  });

  const deleteRuleMutation = useMutation({
    mutationFn: (id: string) =>
      apiClient<void>(`/api/v1/agent/risk-rules/${id}`, { method: 'DELETE' }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: queryKeys.riskRules.all });
      setDeleteTarget(null);
    },
  });

  // Mutations - permissions matrix ----------------------------------------
  const saveMatrixMutation = useMutation({
    mutationFn: (body: PermissionMatrix) =>
      apiClient<PermissionMatrix>('/api/v1/agent/permissions', { method: 'PUT', body }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: queryKeys.permissions.all });
    },
  });

  // Helpers - rules -------------------------------------------------------
  const validate = useCallback((): boolean => {
    const next: Partial<Record<keyof RiskRuleFormData, string>> = {};
    if (!form.pattern.trim()) next.pattern = 'Pattern is required';
    setErrors(next);
    return Object.keys(next).length === 0;
  }, [form]);

  const closeDialog = useCallback(() => {
    setDialogOpen(false);
    setEditingRule(null);
    setForm({ ...EMPTY_RULE_FORM });
    setErrors({});
  }, []);

  const openAdd = useCallback(() => {
    setEditingRule(null);
    setForm({ ...EMPTY_RULE_FORM });
    setErrors({});
    setDialogOpen(true);
  }, []);

  const openEdit = useCallback((rule: RiskRule) => {
    setEditingRule(rule);
    setForm({
      pattern: rule.pattern,
      riskLevel: rule.riskLevel,
      action: rule.action,
      description: rule.description ?? '',
    });
    setErrors({});
    setDialogOpen(true);
  }, []);

  const handleChange = useCallback(
    (field: keyof RiskRuleFormData, value: string | number) => {
      setForm((prev) => ({ ...prev, [field]: value }));
      setErrors((prev) => {
        const next = { ...prev };
        delete next[field];
        return next;
      });
    },
    [],
  );

  const handleSubmit = useCallback(() => {
    if (!validate()) return;
    const body: Record<string, unknown> = {
      pattern: form.pattern.trim(),
      riskLevel: form.riskLevel,
      action: form.action,
      description: form.description.trim(),
    };

    if (editingRule) {
      updateRuleMutation.mutate({ id: editingRule.id, body });
    } else {
      createRuleMutation.mutate(body);
    }
  }, [form, editingRule, validate, createRuleMutation, updateRuleMutation]);

  // Helpers - permissions -------------------------------------------------
  const handleToggle = useCallback((role: Role, perm: Permission) => {
    setMatrix((prev) => {
      const current = prev[role] ?? [];
      const has = current.includes(perm);
      return {
        ...prev,
        [role]: has ? current.filter((p) => p !== perm) : [...current, perm],
      };
    });
  }, []);

  const handleSaveMatrix = useCallback(() => {
    saveMatrixMutation.mutate(matrix);
  }, [matrix, saveMatrixMutation]);

  const isRuleSaving = createRuleMutation.isPending || updateRuleMutation.isPending;

  // Render ---------------------------------------------------------------
  return (
    <div className="space-y-8">
      {/* Header */}
      <div>
        <h1 className="text-2xl font-bold">{t('title')}</h1>
        <p className="text-sm text-muted-foreground mt-1">
          {t('subtitle')}
        </p>
      </div>

      {/* ---- Risk Rules Section ---- */}
      <div>
        <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-4">
          <h2 className="text-lg font-semibold">{t('riskRules.title')}</h2>
          <button
            onClick={openAdd}
            className="px-4 py-2 text-sm rounded-md bg-primary text-primary-foreground hover:bg-primary/90 whitespace-nowrap"
          >
            {t('riskRules.addRule')}
          </button>
        </div>

        {/* Error state */}
        {rulesError && (
          <div className="p-4 mb-4 rounded-md border border-destructive/50 bg-destructive/10 text-destructive text-sm">
            {t('riskRules.loadError')} {(rulesError as Error).message}
          </div>
        )}

        {/* Loading */}
        {rulesLoading && (
          <div className="text-sm text-muted-foreground py-12 text-center">
            {t('riskRules.loading')}
          </div>
        )}

        {/* Rules table */}
        {!rulesLoading && !rulesError && (
          <div className="border rounded-lg overflow-hidden">
            <div className="overflow-x-auto">
              <table className="w-full text-sm">
                <thead>
                  <tr className="border-b bg-muted/50">
                    <th className="text-left px-4 py-3 font-medium">{t('riskRules.table.pattern')}</th>
                    <th className="text-left px-4 py-3 font-medium">{t('riskRules.table.riskLevel')}</th>
                    <th className="text-left px-4 py-3 font-medium">{t('riskRules.table.action')}</th>
                    <th className="text-left px-4 py-3 font-medium">{t('riskRules.table.description')}</th>
                    <th className="text-right px-4 py-3 font-medium">{t('riskRules.table.actions')}</th>
                  </tr>
                </thead>
                <tbody>
                  {rules.length === 0 ? (
                    <tr>
                      <td
                        colSpan={5}
                        className="text-center text-muted-foreground py-12"
                      >
                        {t('riskRules.empty')}
                      </td>
                    </tr>
                  ) : (
                    rules.map((rule) => (
                      <tr
                        key={rule.id}
                        className="border-b last:border-b-0 hover:bg-muted/30 transition-colors"
                      >
                        <td className="px-4 py-3">
                          <code className="px-1.5 py-0.5 rounded bg-muted font-mono text-xs">
                            {rule.pattern}
                          </code>
                        </td>
                        <td className="px-4 py-3">
                          <RiskBadge level={rule.riskLevel} />
                        </td>
                        <td className="px-4 py-3">
                          <ActionBadge action={rule.action} />
                        </td>
                        <td className="px-4 py-3 text-muted-foreground max-w-xs truncate">
                          {rule.description || '--'}
                        </td>
                        <td className="px-4 py-3 text-right">
                          <div className="flex items-center justify-end gap-2">
                            <button
                              onClick={() => openEdit(rule)}
                              className="px-3 py-1 text-xs rounded-md border border-input hover:bg-accent transition-colors"
                            >
                              {tc('edit')}
                            </button>
                            <button
                              onClick={() => setDeleteTarget(rule)}
                              className="px-3 py-1 text-xs rounded-md border border-destructive/50 text-destructive hover:bg-destructive/10 transition-colors"
                            >
                              {tc('delete')}
                            </button>
                          </div>
                        </td>
                      </tr>
                    ))
                  )}
                </tbody>
              </table>
            </div>
          </div>
        )}
      </div>

      {/* ---- Permission Matrix Section ---- */}
      {matrixLoading ? (
        <div className="text-sm text-muted-foreground py-12 text-center">
          {tc('loading')}
        </div>
      ) : (
        <PermissionMatrixSection
          matrix={matrix}
          saving={saveMatrixMutation.isPending}
          onToggle={handleToggle}
          onSave={handleSaveMatrix}
        />
      )}

      {/* Add / Edit rule dialog */}
      <RuleDialog
        open={dialogOpen}
        title={editingRule ? t('riskRules.editRule') : t('riskRules.addRule')}
        form={form}
        errors={errors}
        saving={isRuleSaving}
        onClose={closeDialog}
        onChange={handleChange}
        onSubmit={handleSubmit}
      />

      {/* Delete confirmation dialog */}
      <DeleteRuleDialog
        open={!!deleteTarget}
        pattern={deleteTarget?.pattern ?? ''}
        deleting={deleteRuleMutation.isPending}
        onClose={() => setDeleteTarget(null)}
        onConfirm={() => {
          if (deleteTarget) deleteRuleMutation.mutate(deleteTarget.id);
        }}
      />
    </div>
  );
}
