import type { FormEvent } from 'react';
import { useMemo, useState } from 'react';
import { ClipboardList, FileCheck, KeyRound, Loader2, UserCircle } from 'lucide-react';

import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { ModuleHeader } from '@/components/ui/module-header';
import { NativeSelect } from '@/components/ui/native-select';
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table';
import { useAuth } from '@/contexts/useAuth';
import { useIamCapabilities } from '@/business/iam-capabilities/hooks';
import { getAuthRoleLabel } from '@/business/auth/selectors';
import { hasPermission } from '@/business/auth/permissions';
import { changePassword, updateOwnProfile, updateOrganization } from '@/business/profile/api';
import {
  buildProfileDocumentAcknowledgmentRows,
  buildProfileQuizResultRows,
} from '@/business/profile/selectors';
import { getErrorMessage } from '@/shared/errors/errorMessages';
import { USER_NAME_PREFIX_OPTIONS } from '@/shared/constants/users';
import { ImageUpload } from '@/components/common/ImageUpload';
import { useCurrentPersonalityResultHistory } from '@/business/personality/queryHooks';
import { useMySafetyQuizStatus } from '@/business/safety-quiz/hooks';
import { useTodayZoneCheckIn } from '@/business/zone-checkin/hooks';
import { canZoneCheckIn } from '@/business/zone-checkin/selectors';
import { usePolicies, usePolicyAcknowledgments } from '@/business/policies/hooks';
import { useSafetyProtocols } from '@/business/safety-protocols/hooks';

interface StatusMessage {
  readonly type: 'success' | 'error';
  readonly text: string;
}

const formControlClassName =
  'border-slate-600 bg-slate-950/80 text-slate-100 placeholder:text-slate-500 focus-visible:ring-sky-400 focus-visible:ring-offset-slate-950';

const profileCardClassName =
  'border-slate-600/70 bg-slate-900/80 shadow-lg shadow-black/20';

const formPanelClassName =
  'rounded-lg border border-slate-600/80 bg-slate-950/45 p-4';

function StatusBanner({ status }: { status: StatusMessage | null }) {
  if (!status) {
    return null;
  }

  const className =
    status.type === 'success'
      ? 'border-emerald-500/30 bg-emerald-500/10 text-emerald-200'
      : 'border-red-500/30 bg-red-500/10 text-red-200';

  return (
    <div className={`rounded-lg border px-3 py-2 text-sm ${className}`}>{status.text}</div>
  );
}

function ReadOnlyField({ label, value }: { label: string; value: string }) {
  return (
    <div className="rounded-lg border border-slate-700/70 bg-slate-950/55 px-3 py-2">
      <p className="text-xs font-medium text-slate-400">{label}</p>
      <p className="mt-1 text-sm font-semibold text-slate-100">{value || '—'}</p>
    </div>
  );
}

export default function ProfilePage() {
  const { user, profile, refreshUser } = useAuth();
  const capabilitiesQuery = useIamCapabilities();
  const isExternalProfileUser =
    user?.app_role?.name === 'student' || user?.app_role?.name === 'guardian';
  const canShowQuizResults = Boolean(user) && !isExternalProfileUser;
  const safetyQuizStatus = useMySafetyQuizStatus(undefined, canShowQuizResults);
  const personalityHistoryStatus = useCurrentPersonalityResultHistory(canShowQuizResults);
  const canUseZoneCheckin = canZoneCheckIn(user);
  const zoneCheckinStatus = useTodayZoneCheckIn({ enabled: canShowQuizResults && canUseZoneCheckin });
  const canReadAcknowledgedDocuments = hasPermission(user, 'ACK_POLICY');
  const policyAcknowledgmentsStatus = usePolicyAcknowledgments(canReadAcknowledgedDocuments);
  const handbookPoliciesStatus = usePolicies(canReadAcknowledgedDocuments);
  const safetyProtocolsStatus = useSafetyProtocols(canReadAcknowledgedDocuments);

  const [namePrefix, setNamePrefix] = useState<string>(user?.name_prefix ?? '');
  const [firstName, setFirstName] = useState<string>(user?.firstName ?? '');
  const [lastName, setLastName] = useState<string>(user?.lastName ?? '');
  const [phoneNumber, setPhoneNumber] = useState<string>(user?.phoneNumber ?? '');
  const [email, setEmail] = useState<string>(user?.email ?? '');
  const [profileSaving, setProfileSaving] = useState(false);
  const [profileStatus, setProfileStatus] = useState<StatusMessage | null>(null);

  const [currentPassword, setCurrentPassword] = useState('');
  const [newPassword, setNewPassword] = useState('');
  const [confirmPassword, setConfirmPassword] = useState('');
  const [passwordSaving, setPasswordSaving] = useState(false);
  const [passwordStatus, setPasswordStatus] = useState<StatusMessage | null>(null);

  const [avatar, setAvatar] = useState<string | null>(user?.avatar ?? null);
  const [avatarStatus, setAvatarStatus] = useState<StatusMessage | null>(null);
  const [organizationName, setOrganizationName] = useState(user?.organizations?.name ?? '');
  const [organizationLogo, setOrganizationLogo] = useState<string | null>(
    user?.organizations?.logo ?? null,
  );
  const [organizationSaving, setOrganizationSaving] = useState(false);
  const [organizationStatus, setOrganizationStatus] = useState<StatusMessage | null>(null);

  const roleLabel = profile ? getAuthRoleLabel(profile.role) : '—';
  const canEditOwnOrganization = capabilitiesQuery.data?.canEditOwnOrganization === true
    && Boolean(user?.organizations?.id);

  const tenantChain = useMemo(() => {
    const parts = [
      user?.organizations?.name,
      user?.school?.name,
      user?.campus?.name ?? user?.campus?.code,
      user?.classRoom?.name,
    ].filter((part): part is string => Boolean(part));
    return parts.length > 0 ? parts.join(' › ') : 'Platform';
  }, [user]);

  const quizResultRows = useMemo(
    () => buildProfileQuizResultRows(
      safetyQuizStatus.data?.result ?? null,
      personalityHistoryStatus.data ?? [],
      zoneCheckinStatus.isCheckedInToday && zoneCheckinStatus.todayZone
        ? {
            date: zoneCheckinStatus.todayDate ?? new Date().toISOString().slice(0, 10),
            zone: zoneCheckinStatus.todayZone,
            isCheckedInToday: true,
          }
        : null,
      canUseZoneCheckin,
    ),
    [
      personalityHistoryStatus.data,
      safetyQuizStatus.data?.result,
      zoneCheckinStatus.isCheckedInToday,
      zoneCheckinStatus.todayDate,
      zoneCheckinStatus.todayZone,
      canUseZoneCheckin,
    ],
  );
  const documentAcknowledgmentRows = useMemo(
    () => buildProfileDocumentAcknowledgmentRows(
      handbookPoliciesStatus.data ?? [],
      safetyProtocolsStatus.data ?? [],
      policyAcknowledgmentsStatus.data ?? [],
    ),
    [
      handbookPoliciesStatus.data,
      policyAcknowledgmentsStatus.data,
      safetyProtocolsStatus.data,
    ],
  );

  if (!user) {
    return null;
  }

  async function handleProfileSubmit(event: FormEvent) {
    event.preventDefault();
    setProfileStatus(null);
    setProfileSaving(true);
    try {
      await updateOwnProfile({
        name_prefix: namePrefix === '' ? null : namePrefix,
        firstName: firstName.trim(),
        lastName: lastName.trim(),
        phoneNumber: phoneNumber.trim() || null,
        email: email.trim(),
      });
      await refreshUser();
      setProfileStatus({ type: 'success', text: 'Profile updated.' });
    } catch (error) {
      setProfileStatus({ type: 'error', text: getErrorMessage(error, 'Could not update profile') });
    } finally {
      setProfileSaving(false);
    }
  }

  async function handleAvatarChange(privateUrl: string | null) {
    setAvatar(privateUrl);
    setAvatarStatus(null);
    try {
      await updateOwnProfile({ avatar: privateUrl });
      await refreshUser();
      setAvatarStatus({
        type: 'success',
        text: privateUrl ? 'Avatar updated.' : 'Avatar removed.',
      });
    } catch (error) {
      setAvatarStatus({ type: 'error', text: getErrorMessage(error, 'Could not update avatar') });
    }
  }

  async function handlePasswordSubmit(event: FormEvent) {
    event.preventDefault();
    setPasswordStatus(null);

    if (newPassword !== confirmPassword) {
      setPasswordStatus({ type: 'error', text: 'New password and confirmation do not match.' });
      return;
    }

    setPasswordSaving(true);
    try {
      await changePassword(currentPassword, newPassword);
      setCurrentPassword('');
      setNewPassword('');
      setConfirmPassword('');
      setPasswordStatus({ type: 'success', text: 'Password updated.' });
    } catch (error) {
      setPasswordStatus({ type: 'error', text: getErrorMessage(error, 'Could not update password') });
    } finally {
      setPasswordSaving(false);
    }
  }

  async function handleOrganizationSubmit(event: FormEvent) {
    event.preventDefault();
    const organizationId = user?.organizations?.id;
    if (!organizationId) return;
    setOrganizationStatus(null);
    setOrganizationSaving(true);
    try {
      await updateOrganization(organizationId, {
        name: organizationName.trim(),
        logo: organizationLogo ?? undefined,
      });
      await refreshUser();
      setOrganizationStatus({ type: 'success', text: 'Organization profile updated.' });
    } catch (error) {
      setOrganizationStatus({
        type: 'error',
        text: getErrorMessage(error, 'Could not update organization profile'),
      });
    } finally {
      setOrganizationSaving(false);
    }
  }

  return (
    <div className="space-y-6 p-4 md:p-6">
      <ModuleHeader
        title="My Profile"
        description="Manage your name, email, and password."
        icon={UserCircle}
        iconClassName="bg-gradient-to-br from-violet-500 to-amber-400"
      />

      <div className="space-y-6">
        <Card className={profileCardClassName}>
          <CardHeader className="border-b border-slate-700/70 px-4 py-4 md:px-5">
            <CardTitle className="text-base text-slate-50">Account details</CardTitle>
          </CardHeader>
          <CardContent className="px-4 pb-4 md:px-5">
            <div className="space-y-5 pt-6">
              <div className={`${formPanelClassName} space-y-4`}>
                <div>
                  <p className="text-sm font-semibold text-slate-100">Profile identity</p>
                  <p className="mt-1 text-xs text-slate-300">
                    Your visible name, contact details, and avatar.
                  </p>
                </div>
                <div className="grid gap-5 lg:grid-cols-[auto_1fr]">
                  <ImageUpload
                    value={avatar}
                    onChange={handleAvatarChange}
                    table="users"
                    field="avatar"
                    label="Avatar"
                    shape="square"
                    previewSize="lg"
                  />
                  <div className="grid content-start gap-3 sm:grid-cols-2">
                    <ReadOnlyField label="Role" value={roleLabel} />
                    <ReadOnlyField label="Scope" value={tenantChain} />
                  </div>
                </div>
                <StatusBanner status={avatarStatus} />
              </div>

              <form className="space-y-5" onSubmit={handleProfileSubmit}>
                <div className={`${formPanelClassName} space-y-4`}>
                  <div className="grid gap-4 md:grid-cols-4">
                    <div className="space-y-1.5">
                      <Label htmlFor="name_prefix" className="text-slate-100">Title</Label>
                      <NativeSelect
                        id="name_prefix"
                        value={namePrefix}
                        className={formControlClassName}
                        onChange={(event) => setNamePrefix(event.target.value)}
                      >
                        <option value="">None</option>
                        {USER_NAME_PREFIX_OPTIONS.map((option) => (
                          <option key={option.value} value={option.value}>
                            {option.label}
                          </option>
                        ))}
                      </NativeSelect>
                    </div>
                    <div className="space-y-1.5">
                      <Label htmlFor="firstName" className="text-slate-100">First name</Label>
                      <Input
                        id="firstName"
                        value={firstName}
                        className={formControlClassName}
                        onChange={(event) => setFirstName(event.target.value)}
                      />
                    </div>
                    <div className="space-y-1.5">
                      <Label htmlFor="lastName" className="text-slate-100">Last name</Label>
                      <Input
                        id="lastName"
                        value={lastName}
                        className={formControlClassName}
                        onChange={(event) => setLastName(event.target.value)}
                      />
                    </div>
                    <div className="space-y-1.5">
                      <Label htmlFor="phoneNumber" className="text-slate-100">Phone number</Label>
                      <Input
                        id="phoneNumber"
                        type="tel"
                        value={phoneNumber}
                        className={formControlClassName}
                        onChange={(event) => setPhoneNumber(event.target.value)}
                      />
                    </div>
                  </div>

                  <div className="space-y-1.5">
                    <Label htmlFor="email" className="text-slate-100">Email</Label>
                    <Input
                      id="email"
                      type="email"
                      value={email}
                      className={formControlClassName}
                      onChange={(event) => setEmail(event.target.value)}
                    />
                  </div>
                </div>

                <StatusBanner status={profileStatus} />

                <div className="flex justify-end">
                  <Button type="submit" disabled={profileSaving}>
                    {profileSaving && <Loader2 size={16} className="mr-2 animate-spin" />}
                    Save changes
                  </Button>
                </div>
              </form>
            </div>
          </CardContent>
        </Card>

        {canEditOwnOrganization && (
          <Card className={profileCardClassName}>
            <CardHeader className="border-b border-slate-700/70 px-4 py-4 md:px-5">
              <CardTitle className="text-base text-slate-50">Organization profile</CardTitle>
            </CardHeader>
            <CardContent className="px-4 pb-4 md:px-5">
              <form className="space-y-5 pt-6" onSubmit={handleOrganizationSubmit}>
                <div className={`${formPanelClassName} space-y-4`}>
                  <div>
                    <p className="text-sm font-semibold text-slate-100">Organization identity</p>
                    <p className="mt-1 text-xs text-slate-300">
                      The name and logo shown for your organization.
                    </p>
                  </div>
                  <ImageUpload
                    value={organizationLogo}
                    onChange={setOrganizationLogo}
                    table="organizations"
                    field="logo"
                    label="Logo"
                  />
                  <div className="space-y-1.5">
                    <Label htmlFor="organizationName" className="text-slate-100">Organization name</Label>
                    <Input
                      id="organizationName"
                      value={organizationName}
                      className={formControlClassName}
                      onChange={(event) => setOrganizationName(event.target.value)}
                      required
                    />
                  </div>
                </div>

                <StatusBanner status={organizationStatus} />

                <div className="flex justify-end">
                  <Button type="submit" disabled={organizationSaving}>
                    {organizationSaving && <Loader2 size={16} className="mr-2 animate-spin" />}
                    Save organization
                  </Button>
                </div>
              </form>
            </CardContent>
          </Card>
        )}
      </div>

      {canShowQuizResults && (
        <Card className={profileCardClassName}>
          <CardHeader className="border-b border-slate-700/70 px-4 py-4 md:px-5">
            <CardTitle className="flex items-center gap-2 text-base text-slate-50">
              <ClipboardList size={16} />
              Quiz results
            </CardTitle>
          </CardHeader>
          <CardContent className="px-4 pb-4 md:px-5">
            <div className={`${formPanelClassName} mt-6`}>
              {safetyQuizStatus.isLoading || personalityHistoryStatus.isLoading || zoneCheckinStatus.isLoading ? (
                <p className="text-sm text-slate-300">Loading quiz results...</p>
              ) : (
                <div className="overflow-hidden rounded-lg border border-slate-700/70">
                  <Table>
                    <TableHeader>
                      <TableRow className="border-slate-700/70 bg-slate-950/60 hover:bg-slate-950/60">
                        <TableHead className="h-auto p-3 text-slate-400">Quiz</TableHead>
                        <TableHead className="h-auto p-3 text-slate-400">Category</TableHead>
                        <TableHead className="h-auto p-3 text-slate-400">Result</TableHead>
                        <TableHead className="h-auto p-3 text-slate-400">Completed</TableHead>
                      </TableRow>
                    </TableHeader>
                    <TableBody>
                    {quizResultRows.map((result) => (
                      <TableRow
                        key={result.id}
                        className="border-slate-800/80 hover:bg-slate-800/20"
                      >
                        <TableCell className="p-3">
                          <p className="font-semibold text-slate-100">{result.quiz}</p>
                        </TableCell>
                        <TableCell className="p-3 text-slate-300">{result.category}</TableCell>
                        <TableCell className={`p-3 font-semibold ${
                          result.status === 'complete' ? 'text-slate-100' : 'text-amber-300'
                        }`}>
                          {result.result}
                        </TableCell>
                        <TableCell className="p-3 text-slate-300">{result.completed}</TableCell>
                      </TableRow>
                    ))}
                    </TableBody>
                  </Table>
                </div>
              )}
            </div>
          </CardContent>
        </Card>
      )}

      {canReadAcknowledgedDocuments && (
        <Card className={profileCardClassName}>
          <CardHeader className="border-b border-slate-700/70 px-4 py-4 md:px-5">
            <CardTitle className="flex items-center gap-2 text-base text-slate-50">
              <FileCheck size={16} />
              Document acknowledgments
            </CardTitle>
          </CardHeader>
          <CardContent className="px-4 pb-4 md:px-5">
            <div className={`${formPanelClassName} mt-6`}>
              {(
                policyAcknowledgmentsStatus.isLoading
                || handbookPoliciesStatus.isLoading
                || safetyProtocolsStatus.isLoading
              ) ? (
                <p className="text-sm text-slate-300">Loading document acknowledgments...</p>
              ) : documentAcknowledgmentRows.length === 0 ? (
                <p className="text-sm text-slate-300">
                  No current documents are assigned yet.
                </p>
              ) : (
                <div className="overflow-hidden rounded-lg border border-slate-700/70">
                  <Table>
                    <TableHeader>
                      <TableRow className="border-slate-700/70 bg-slate-950/60 hover:bg-slate-950/60">
                        <TableHead className="h-auto p-3 text-slate-400">Document</TableHead>
                        <TableHead className="h-auto p-3 text-slate-400">Category</TableHead>
                        <TableHead className="h-auto p-3 text-slate-400">Version</TableHead>
                        <TableHead className="h-auto p-3 text-slate-400">Acknowledged on</TableHead>
                      </TableRow>
                    </TableHeader>
                    <TableBody>
                      {documentAcknowledgmentRows.map((document) => (
                        <TableRow
                          key={document.id}
                          className="border-slate-800/80 hover:bg-slate-800/20"
                        >
                          <TableCell className="p-3">
                            <div className="flex flex-wrap items-center gap-2">
                              <p className="font-semibold text-slate-100">{document.title}</p>
                              <span className={`rounded-full px-2 py-0.5 text-xs font-semibold ${
                                document.status === 'acknowledged'
                                  ? 'bg-emerald-500/15 text-emerald-200 ring-1 ring-emerald-400/30'
                                  : 'bg-red-500/15 text-red-200 ring-1 ring-red-400/30'
                              }`}>
                                {document.status === 'acknowledged'
                                  ? 'Acknowledged'
                                  : 'Not acknowledged'}
                              </span>
                            </div>
                          </TableCell>
                          <TableCell className="p-3 text-slate-300">{document.category}</TableCell>
                          <TableCell className="p-3 text-slate-300">{document.version}</TableCell>
                          <TableCell className="p-3 text-slate-300">
                            {document.acknowledgedAt
                              ? new Date(document.acknowledgedAt).toLocaleDateString()
                              : '—'}
                          </TableCell>
                        </TableRow>
                      ))}
                    </TableBody>
                  </Table>
                </div>
              )}
            </div>
          </CardContent>
        </Card>
      )}

      <Card className={profileCardClassName}>
        <CardHeader className="border-b border-slate-700/70 px-4 py-4 md:px-5">
          <CardTitle className="flex items-center gap-2 text-base text-slate-50">
            <KeyRound size={16} />
            Change password
          </CardTitle>
        </CardHeader>
        <CardContent className="px-4 pb-4 md:px-5">
          <form className="space-y-5 pt-6" onSubmit={handlePasswordSubmit}>
            <div className={`${formPanelClassName} space-y-4`}>
              <div>
                <p className="text-sm font-semibold text-slate-100">Password credentials</p>
                <p className="mt-1 text-xs text-slate-300">
                  Use your current password before setting a new one.
                </p>
              </div>
              <div className="space-y-1.5">
                <Label htmlFor="currentPassword" className="text-slate-100">Current password</Label>
                <Input
                  id="currentPassword"
                  type="password"
                  autoComplete="current-password"
                  value={currentPassword}
                  className={formControlClassName}
                  onChange={(event) => setCurrentPassword(event.target.value)}
                  required
                />
              </div>
              <div className="grid gap-4 md:grid-cols-2">
                <div className="space-y-1.5">
                  <Label htmlFor="newPassword" className="text-slate-100">New password</Label>
                  <Input
                    id="newPassword"
                    type="password"
                    autoComplete="new-password"
                    value={newPassword}
                    className={formControlClassName}
                    onChange={(event) => setNewPassword(event.target.value)}
                    required
                  />
                </div>
                <div className="space-y-1.5">
                  <Label htmlFor="confirmPassword" className="text-slate-100">Confirm new password</Label>
                  <Input
                    id="confirmPassword"
                    type="password"
                    autoComplete="new-password"
                    value={confirmPassword}
                    className={formControlClassName}
                    onChange={(event) => setConfirmPassword(event.target.value)}
                    required
                  />
                </div>
              </div>
            </div>
            <StatusBanner status={passwordStatus} />

            <div className="flex justify-end">
              <Button type="submit" disabled={passwordSaving}>
                {passwordSaving && <Loader2 size={16} className="mr-2 animate-spin" />}
                Update password
              </Button>
            </div>
          </form>
        </CardContent>
      </Card>
    </div>
  );
}
