'use client';

import { DASHBOARD_MODULES, type DashboardAccessRule, type DashboardModuleId } from '@nexumi/shared';
import { Plus, Trash2 } from 'lucide-react';
import { FieldAnchor } from '@/components/layout/field-anchor';
import { useTranslations } from '@/components/locale-provider';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { DiscordRoleSelect } from '@/components/ui/discord-role-select';
import { Label } from '@/components/ui/label';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import type { SettingsSaveResult } from './settings-form';
import { SettingsForm } from './settings-form';

interface LocalRule {
  clientKey: string;
  roleId: string;
  modulesMode: 'all' | 'specific';
  selectedModules: DashboardModuleId[];
}

function toLocalRules(rules: DashboardAccessRule[]): LocalRule[] {
  return rules.map((rule, index) => ({
    clientKey: rule.id ?? `existing-${index}`,
    roleId: rule.roleId,
    modulesMode: rule.modules === 'all' ? 'all' : 'specific',
    selectedModules: rule.modules === 'all' ? [] : rule.modules
  }));
}

function toRemoteRules(rules: LocalRule[]): DashboardAccessRule[] {
  return rules.map((rule) => ({
    roleId: rule.roleId,
    modules: rule.modulesMode === 'all' ? 'all' : rule.selectedModules
  }));
}

async function saveAccessRules(guildId: string, rules: LocalRule[]): Promise<SettingsSaveResult> {
  try {
    const response = await fetch(`/api/guilds/${guildId}/access-rules`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ rules: toRemoteRules(rules) })
    });
    if (!response.ok) {
      const body = (await response.json().catch(() => null)) as { error?: string } | null;
      return { ok: false, error: body?.error ?? `Request failed with status ${response.status}` };
    }
    return { ok: true };
  } catch {
    return { ok: false, error: 'Network error' };
  }
}

function AccessRuleRow({
  guildId,
  rule,
  onChange,
  onRemove,
  anchorIds
}: {
  guildId: string;
  rule: LocalRule;
  onChange: (rule: LocalRule) => void;
  onRemove: () => void;
  anchorIds?: boolean;
}) {
  const t = useTranslations();

  function toggleModule(moduleId: DashboardModuleId, checked: boolean) {
    const next = checked
      ? [...rule.selectedModules, moduleId]
      : rule.selectedModules.filter((id) => id !== moduleId);
    onChange({ ...rule, selectedModules: next });
  }

  const roleBlock = (
    <div className="flex items-start justify-between gap-4">
      <div className="flex-1 space-y-2">
        <Label>{t('access.roleIdLabel')}</Label>
        <div className="max-w-xs">
          <DiscordRoleSelect
            guildId={guildId}
            value={rule.roleId}
            onChange={(roleId) => onChange({ ...rule, roleId })}
            placeholder={t('access.roleIdPlaceholder')}
          />
        </div>
        <p className="text-xs text-muted-foreground">{t('access.roleIdHint')}</p>
      </div>
      <Button type="button" variant="ghost" size="icon" onClick={onRemove} aria-label={t('access.removeRule')}>
        <Trash2 className="size-4" />
      </Button>
    </div>
  );

  const modulesBlock = (
    <div className="space-y-2">
      <Label>{t('access.modulesLabel')}</Label>
      <Select
        value={rule.modulesMode}
        onValueChange={(mode) => onChange({ ...rule, modulesMode: mode as 'all' | 'specific' })}
      >
        <SelectTrigger className="w-56">
          <SelectValue />
        </SelectTrigger>
        <SelectContent>
          <SelectItem value="all">{t('access.allModulesOption')}</SelectItem>
          <SelectItem value="specific">{t('access.specificModulesOption')}</SelectItem>
        </SelectContent>
      </Select>

      {rule.modulesMode === 'specific' && (
        <div className="grid grid-cols-2 gap-2 pt-2 sm:grid-cols-3">
          {DASHBOARD_MODULES.map((module) => (
            <label key={module.id} className="flex items-center gap-2 text-sm">
              <input
                type="checkbox"
                className="size-4 rounded border-input accent-primary"
                checked={rule.selectedModules.includes(module.id)}
                onChange={(event) => toggleModule(module.id, event.target.checked)}
              />
              {t(`modules.${module.id}.label`)}
            </label>
          ))}
        </div>
      )}
    </div>
  );

  return (
    <div className="space-y-4 rounded-md border border-border p-4">
      {anchorIds ? <FieldAnchor id="field-access-role">{roleBlock}</FieldAnchor> : roleBlock}
      {anchorIds ? <FieldAnchor id="field-access-modules">{modulesBlock}</FieldAnchor> : modulesBlock}
    </div>
  );
}

interface AccessRulesFormProps {
  guildId: string;
  initialRules: DashboardAccessRule[];
}

export function AccessRulesForm({ guildId, initialRules }: AccessRulesFormProps) {
  const t = useTranslations();

  return (
    <SettingsForm<LocalRule[]>
      initialValue={toLocalRules(initialRules)}
      onSave={(value) => saveAccessRules(guildId, value)}
    >
      {({ value, setValue }) => (
        <Card>
          <CardHeader>
            <CardTitle>{t('access.title')}</CardTitle>
            <CardDescription>{t('access.description')}</CardDescription>
          </CardHeader>
          <CardContent className="space-y-4">
            {value.length === 0 && (
              <>
                <FieldAnchor id="field-access-role">
                  <p className="text-sm text-muted-foreground">{t('access.noRules')}</p>
                </FieldAnchor>
                <FieldAnchor id="field-access-modules">
                  <span className="sr-only">{t('access.modulesLabel')}</span>
                </FieldAnchor>
              </>
            )}

            {value.map((rule, index) => (
              <AccessRuleRow
                key={rule.clientKey}
                guildId={guildId}
                rule={rule}
                anchorIds={index === 0}
                onChange={(updated) =>
                  setValue((prev) => prev.map((entry) => (entry.clientKey === rule.clientKey ? updated : entry)))
                }
                onRemove={() => setValue((prev) => prev.filter((entry) => entry.clientKey !== rule.clientKey))}
              />
            ))}

            <Button
              type="button"
              variant="outline"
              onClick={() =>
                setValue((prev) => [
                  ...prev,
                  {
                    clientKey: `new-${Date.now()}-${prev.length}`,
                    roleId: '',
                    modulesMode: 'all',
                    selectedModules: []
                  }
                ])
              }
            >
              <Plus className="size-4" />
              {t('access.addRule')}
            </Button>
          </CardContent>
        </Card>
      )}
    </SettingsForm>
  );
}
