import DataTable from '@/components/common/data-table';
import PageHeading from '@/components/common/page-heading';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import { Separator } from '@/components/ui/separator';
import { Skeleton } from '@/components/ui/skeleton';
import { createRequest } from '@/data/request/create-request';
import { useApiSWR } from '@/hooks/useSWR';
import { SharedData } from '@/types';
import { usePage } from '@inertiajs/react';
import {
  CheckCircleIcon,
  DatabaseIcon,
  WarningCircleIcon,
} from '@phosphor-icons/react';
import { SortingState } from '@tanstack/react-table';
import { useState, useTransition } from 'react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';

type TPendingUpdate = {
  version: string;
  name: string;
  file: string;
};

type TDatabaseStatus = {
  current_version: string;
  latest_version: string;
  up_to_date: boolean;
  supported: boolean;
  driver: string;
  pending: TPendingUpdate[];
};

const ApplicationInfo = () => {
  const [sorting, setSorting] = useState<SortingState>([]);
  const [updateDialogOpen, setUpdateDialogOpen] = useState(false);
  const [isUpdating, startUpdateTransition] = useTransition();
  const { t } = useTranslation();
  const { auth } = usePage<SharedData>().props;

  const canUpdate =
    auth.roles?.includes('super-admin') ||
    auth.permissions?.includes('setting-edit');

  type TApplicationInfo = {
    app_environment: string;
    debug_mode: string;
    app_version: string;
    app_url: string;
    php_version: string;
    laravel_version: string;
    timezone: string;
    database_connection: string;
    database_version: string;
  };

  const { data, isLoading } = useApiSWR<TApplicationInfo>(
    '/admin/settings/server-info',
  );

  const {
    data: dbStatus,
    isLoading: isStatusLoading,
    mutate: refreshDbStatus,
  } = useApiSWR<TDatabaseStatus>('/admin/settings/database-status');

  const onRunUpdate = () => {
    setUpdateDialogOpen(false);
    startUpdateTransition(async () => {
      const res = await createRequest({
        url: '/api/admin/settings/database-update',
        formData: {},
      });
      if (res?.success) {
        toast.success(res.message);
        refreshDbStatus();
      } else {
        toast.error(res?.message ?? t('Database update failed.'));
      }
    });
  };

  const tableData = data
    ? [
        {
          subject: t('App Environment'),
          info: data.app_environment,
        },
        {
          subject: t('Debug Mode'),
          info: data.debug_mode,
        },
        {
          subject: t('App Version'),
          info: data.app_version,
        },
        {
          subject: t('App URL'),
          info: data.app_url,
        },
        {
          subject: t('PHP Version'),
          info: data.php_version,
        },
        {
          subject: t('Laravel Version'),
          info: data.laravel_version,
        },
        {
          subject: t('Time Zone'),
          info: data.timezone,
        },
        {
          subject: t('Database Connection'),
          info: data.database_connection,
        },
        {
          subject: t('Database Version'),
          info: data.database_version,
        },
      ]
    : [];

  return (
    <>
      <PageHeading
        title={t('Application Info')}
        description={t(
          'View application environment and configuration details.',
        )}
      />

      <div className="mb-4 rounded-xl bg-white p-6 shadow-box">
        <div className="flex flex-wrap items-start justify-between gap-3">
          <div>
            <h3 className="flex items-center gap-2 text-xl font-medium">
              <DatabaseIcon weight="bold" className="size-5 text-black/40" />
              {t('Database Schema')}
            </h3>
            <p className="mt-1 text-sm text-black/50">
              {t(
                'Feature updates ship schema changes as SQL update files. Apply any pending ones here.',
              )}
            </p>
          </div>
          {isStatusLoading ? (
            <Skeleton className="h-6 w-28 rounded-full" />
          ) : (
            dbStatus &&
            (!dbStatus.supported ? (
              <Badge variant="primaryOutline">
                {t('Managed by migrations')}
              </Badge>
            ) : dbStatus.up_to_date ? (
              <Badge variant="successOutline">
                <CheckCircleIcon weight="fill" />
                {t('Up to date')}
              </Badge>
            ) : (
              <Badge variant="warningOutline">
                <WarningCircleIcon weight="fill" />
                {t('Update available')}
              </Badge>
            ))
          )}
        </div>

        <Separator className="my-4" />

        <div className="grid gap-4 sm:grid-cols-2">
          <div>
            <p className="text-sm text-black/50">
              {t('Installed Schema Version')}
            </p>
            <p className="mt-1 text-lg font-medium">
              {isStatusLoading ? (
                <Skeleton className="h-6 w-12" />
              ) : (
                (dbStatus?.current_version ?? '—')
              )}
            </p>
          </div>
          <div>
            <p className="text-sm text-black/50">{t('Latest Available')}</p>
            <p className="mt-1 text-lg font-medium">
              {isStatusLoading ? (
                <Skeleton className="h-6 w-12" />
              ) : (
                (dbStatus?.latest_version ?? '—')
              )}
            </p>
          </div>
        </div>

        {dbStatus && !dbStatus.supported && (
          <p className="mt-4 text-sm text-black/50">
            {t(
              'This install runs on {{driver}}. SQL update files target MySQL only — use `php artisan migrate` instead.',
              { driver: dbStatus.driver },
            )}
          </p>
        )}

        {dbStatus?.supported && dbStatus.pending.length > 0 && (
          <>
            <Separator className="my-4" />

            <p className="mb-2 text-sm font-medium">{t('Pending Updates')}</p>
            <ul className="divide-y divide-muted overflow-hidden rounded-lg border border-muted">
              {dbStatus.pending.map((update) => (
                <li
                  key={update.file}
                  className="flex flex-wrap items-center gap-x-3 gap-y-1 bg-black/[0.02] px-4 py-3"
                >
                  <Badge variant="primaryOutline">v{update.version}</Badge>
                  <span className="text-sm">{update.name}</span>
                  <span className="ms-auto font-mono text-xs text-black/40">
                    {update.file}
                  </span>
                </li>
              ))}
            </ul>
          </>
        )}

        {dbStatus?.supported && !dbStatus.up_to_date && canUpdate && (
          <>
            <Separator className="my-4" />

            <div className="flex justify-end">
              <Button
                loading={isUpdating}
                disabled={isUpdating}
                onClick={() => setUpdateDialogOpen(true)}
              >
                <DatabaseIcon weight="bold" />
                {t('Update Database')}
              </Button>
            </div>
          </>
        )}
      </div>

      <DataTable
        data={tableData}
        sorting={sorting}
        setSorting={setSorting}
        isLoading={isLoading}
        rounded
        structure={[
          {
            accessorKey: 'subject',
            header: t('Subject'),
          },
          {
            accessorKey: 'info',
            header: t('Info'),
            cell: ({ row, getValue }) => {
              const value = getValue();
              if (
                row.original.subject === t('Debug Mode') &&
                value === 'Enabled'
              ) {
                return <Badge variant="success">{value}</Badge>;
              }

              return value;
            },
          },
        ]}
      />

      <Dialog open={updateDialogOpen} onOpenChange={setUpdateDialogOpen}>
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>{t('Update Database')}</DialogTitle>
            <DialogDescription>
              {t(
                'This applies {{count}} pending SQL update file(s) to your database. Back up your database first. The updates are safe to re-run if anything fails.',
                { count: dbStatus?.pending.length ?? 0 },
              )}
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button
              variant="outline"
              onClick={() => setUpdateDialogOpen(false)}
            >
              {t('Cancel')}
            </Button>
            <Button loading={isUpdating} onClick={onRunUpdate}>
              {t('Run Update')}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  );
};

ApplicationInfo.title = 'Application Info';

export default ApplicationInfo;
