import { Role } from '@prisma/client';
import { randomUUID } from 'crypto';
import { readDataFile, writeDataFile } from './local-store';

export type ClinicSettings = {
  clinicName: string;
  brandShortName: string;
  slogan: string;
  fiscalId: string;
  location: string;
  address: string;
  contactEmail: string;
  contactPhone: string;
  websiteUrl: string;
  whatsappPhone: string;
  currency: string;
  documentFooterNote: string;
  defaultDocumentIssuer: string;
  installSupportLabel: string;
  installSupportValue: string;
  androidApkUrl: string;
  iosInstallUrl: string;
  updatedAt: string;
};

type StoredUser = {
  id: string;
  email: string;
  password: string;
  name: string;
  role: Role;
  active: boolean;
  createdAt: string;
  updatedAt: string;
};

const settingsFileName = 'settings.json';
const usersFileName = 'users.json';

export class DuplicateUserEmailError extends Error {
  constructor() {
    super('Ya existe un usuario con ese correo');
    this.name = 'DuplicateUserEmailError';
  }
}

type CreateFallbackUserInput = {
  email: string;
  password: string;
  name: string;
  role: Role;
  active?: boolean;
};

const defaultClinicSettings = (): ClinicSettings => ({
  clinicName: 'DentaFlow Premium',
  brandShortName: 'DentaFlow',
  slogan: 'Gestion odontologica clara para cada jornada clinica.',
  fiscalId: '20556677889',
  location: 'Sede Miraflores',
  address: 'Av. Principal 123, Miraflores, Lima',
  contactEmail: 'contacto@dentaflow.local',
  contactPhone: '+51 900 000 000',
  websiteUrl: '',
  whatsappPhone: '+51 900 000 000',
  currency: 'PEN',
  documentFooterNote: 'Documento de uso clinico y administrativo interno. Verifica los datos antes de emitir o archivar.',
  defaultDocumentIssuer: 'Administracion de la clinica',
  installSupportLabel: 'Soporte de la clinica',
  installSupportValue: 'Solicita a la clinica el enlace final de instalacion o el QR actualizado.',
  androidApkUrl: '',
  iosInstallUrl: '',
  updatedAt: new Date().toISOString(),
});

const defaultUsers = (): StoredUser[] => {
  const now = new Date().toISOString();

  return [
    {
      id: randomUUID(),
      email: 'admin@dentaflow.local',
      password: 'admin123',
      name: 'Administrador DentaFlow',
      role: Role.ADMIN,
      active: true,
      createdAt: now,
      updatedAt: now,
    },
  ];
};

export const getFallbackClinicSettings = async () =>
  readDataFile<ClinicSettings>(settingsFileName, defaultClinicSettings);

export const updateFallbackClinicSettings = async (input: Partial<ClinicSettings>) => {
  const currentSettings = await getFallbackClinicSettings();

  const nextSettings: ClinicSettings = {
    ...currentSettings,
    ...input,
    updatedAt: new Date().toISOString(),
  };

  await writeDataFile(settingsFileName, nextSettings);
  return nextSettings;
};

export const listFallbackUsers = async () => readDataFile<StoredUser[]>(usersFileName, defaultUsers);

export const findFallbackUserByEmail = async (email: string) => {
  const normalizedEmail = email.trim().toLowerCase();
  const users = await listFallbackUsers();
  return users.find((user) => user.email.toLowerCase() === normalizedEmail) ?? null;
};

export const findFallbackUserById = async (userId: string) => {
  const users = await listFallbackUsers();
  return users.find((user) => user.id === userId) ?? null;
};

export const createFallbackUser = async (input: CreateFallbackUserInput) => {
  const users = await listFallbackUsers();
  const normalizedEmail = input.email.trim().toLowerCase();
  const existingUser = users.find((user) => user.email.toLowerCase() === normalizedEmail);

  if (existingUser) {
    throw new DuplicateUserEmailError();
  }

  const now = new Date().toISOString();
  const user: StoredUser = {
    id: randomUUID(),
    email: normalizedEmail,
    password: input.password,
    name: input.name.trim(),
    role: input.role,
    active: input.active ?? true,
    createdAt: now,
    updatedAt: now,
  };

  users.unshift(user);
  await writeDataFile(usersFileName, users);
  return user;
};

export const updateFallbackUserPassword = async (userId: string, nextPassword: string) => {
  const users = await listFallbackUsers();
  const userIndex = users.findIndex((user) => user.id === userId);

  if (userIndex === -1) {
    return null;
  }

  const currentUser = users[userIndex]!;

  const updatedUser: StoredUser = {
    id: currentUser.id,
    email: currentUser.email,
    password: nextPassword,
    name: currentUser.name,
    role: currentUser.role,
    active: currentUser.active,
    createdAt: currentUser.createdAt,
    updatedAt: new Date().toISOString(),
  };

  users[userIndex] = updatedUser;
  await writeDataFile(usersFileName, users);
  return updatedUser;
};

export const sanitizeFallbackUser = (user: StoredUser) => ({
  id: user.id,
  email: user.email,
  name: user.name,
  role: user.role,
  active: user.active,
  createdAt: user.createdAt,
  updatedAt: user.updatedAt,
});
