import { createClient } from '@supabase/supabase-js';
import { createHash, randomBytes } from 'crypto';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
let _client: any = null;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function getSupabaseAdmin(): any {
  if (!_client) {
    _client = createClient(
      process.env.NEXT_PUBLIC_SUPABASE_URL!,
      process.env.SUPABASE_SERVICE_ROLE_KEY!
    );
  }
  return _client;
}

export function generateLicenceKey(): string {
  const part = () => randomBytes(2).toString('hex').toUpperCase();
  return `LAU-${part()}-${part()}-${part()}`;
}

export function hashKey(key: string): string {
  return createHash('sha256').update(key).digest('hex');
}

export function nextMonthReset(): string {
  const d = new Date();
  d.setMonth(d.getMonth() + 1);
  d.setDate(1);
  d.setHours(0, 0, 0, 0);
  return d.toISOString();
}

export async function createLicence(
  email: string,
  plan: string,
  quota: number,
  stripeCustomerId: string,
  stripeSubscriptionId: string,
  resetAt?: string,
): Promise<{ key: string; keyHash: string }> {
  const key     = generateLicenceKey();
  const keyHash = hashKey(key);

  const { error } = await getSupabaseAdmin().from('licences').insert({
    key_hash:               keyHash,
    email,
    plan,
    quota_month:            quota,
    usage_month:            0,
    reset_at:               resetAt ?? nextMonthReset(),
    active:                 true,
    allowed_ip:             null,
    flagged:                false,
    stripe_customer_id:     stripeCustomerId,
    stripe_subscription_id: stripeSubscriptionId,
  });

  if (error) throw new Error('Failed to create licence: ' + error.message);
  return { key, keyHash };
}

export async function resetQuotaOnRenewal(subscriptionId: string, resetAt: string) {
  await getSupabaseAdmin()
    .from('licences')
    .update({ usage_month: 0, reset_at: resetAt, active: true })
    .eq('stripe_subscription_id', subscriptionId);
}

export async function getLicenceByEmail(email: string) {
  const { data } = await getSupabaseAdmin()
    .from('licences')
    .select('*')
    .eq('email', email)
    .order('created_at', { ascending: false })
    .limit(1)
    .single();
  return data;
}

export async function getLicenceBySubscription(subscriptionId: string) {
  const { data } = await getSupabaseAdmin()
    .from('licences')
    .select('*')
    .eq('stripe_subscription_id', subscriptionId)
    .single();
  return data;
}

export async function deactivateLicenceBySubscription(subscriptionId: string) {
  await getSupabaseAdmin()
    .from('licences')
    .update({ active: false })
    .eq('stripe_subscription_id', subscriptionId);
}

export async function reactivateLicenceBySubscription(subscriptionId: string) {
  await getSupabaseAdmin()
    .from('licences')
    .update({ active: true })
    .eq('stripe_subscription_id', subscriptionId);
}

export async function createTrialLicence(email: string): Promise<{ key: string }> {
  const { data: existing } = await getSupabaseAdmin()
    .from('licences')
    .select('id')
    .eq('email', email)
    .limit(1);

  if (existing && existing.length > 0) {
    const err = new Error('already_exists');
    (err as NodeJS.ErrnoException).code = 'already_exists';
    throw err;
  }

  const key     = generateLicenceKey();
  const keyHash = hashKey(key);

  const { error } = await getSupabaseAdmin().from('licences').insert({
    key_hash:    keyHash,
    email,
    plan:        'trial',
    quota_month: 5,
    usage_month: 0,
    reset_at:    '2099-12-31T00:00:00.000Z',
    active:      true,
    allowed_ip:  null,
    flagged:     false,
  });

  if (error) throw new Error('DB: ' + error.message);
  return { key };
}
