import { adapters, newUuid, migrationFields } from '@/services/serviceConfig';
import { auditService } from '@/services/auditService';

const ENTITY = 'Invitation';
const TOKEN_LEN = 48;
const genToken = () => {
  const bytes = crypto.getRandomValues(new Uint8Array(TOKEN_LEN));
  return Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
};
const DAYS = 7;

export const invitationService = {
  list: () => adapters.database.list(ENTITY),
  get: (uuid) => adapters.database.filter(ENTITY, { uuid }).then(r => r[0] || null),
  getByToken: (token) => adapters.database.filter(ENTITY, { token }).then(r => r[0] || null),
  getPendingByEmail: (email) => adapters.database.filter(ENTITY, { email, status: 'pending' }).then(r => r[0] || null),

  create: ({ email, intended_role, permission_preset, custom_permissions, linked_customer_uuid, linked_customer_number, linked_builder_profile_uuid, notes, expiryDays = DAYS }, actor = 'Workshop Owner') => {
    const now = new Date();
    const expiry = new Date(now.getTime() + expiryDays * 86400000);
    const rec = {
      uuid: newUuid('invite'),
      token: genToken(),
      email, intended_role, permission_preset, custom_permissions,
      linked_customer_uuid, linked_customer_number, linked_builder_profile_uuid,
      invited_by_name: actor,
      created_date: now.toISOString(),
      expiry_date: expiry.toISOString(),
      status: 'pending',
      notes,
      ...migrationFields(actor),
    };
    return adapters.database.create(ENTITY, rec).then(r => {
      auditService.record('invitation_created', ENTITY, rec.uuid, `Invited ${email} as ${intended_role}`, actor);
      return r;
    });
  },

  resend: (inv, actor = 'Workshop Owner') => {
    const expiry = new Date(Date.now() + DAYS * 86400000).toISOString();
    return adapters.database.update(ENTITY, inv.id, { token: genToken(), expiry_date: expiry, status: 'pending', revoked_date: null, updated_by_name: actor })
      .then(r => { auditService.record('invitation_resent', ENTITY, inv.uuid, 'Invitation resent', actor); return r; });
  },

  revoke: (inv, actor = 'Workshop Owner') =>
    adapters.database.update(ENTITY, inv.id, { status: 'revoked', revoked_date: new Date().toISOString(), updated_by_name: actor })
      .then(r => { auditService.record('invitation_revoked', ENTITY, inv.uuid, 'Invitation revoked', actor); return r; }),

  accept: async (inv, userId, actor = 'Workshop Owner') => {
    const now = new Date();
    if (inv.status !== 'pending') return { error: 'Invitation is no longer pending.' };
    if (new Date(inv.expiry_date) < now) {
      await adapters.database.update(ENTITY, inv.id, { status: 'expired', updated_by_name: actor });
      return { error: 'This invitation has expired.' };
    }
    await adapters.database.update(ENTITY, inv.id, { status: 'accepted', accepted_date: now.toISOString(), accepted_by_user_id: userId, updated_by_name: actor });
    auditService.record('invitation_accepted', ENTITY, inv.uuid, `Accepted by ${userId}`, actor);
    return { ok: true };
  },

  linkForCopy: (inv) => `${window.location.origin}/invitation/${inv.token}`,
};