import type { UserRole, UserSession } from '@/types';
import { sha256 } from './sha256';

export const SESSION_COOKIE_NAME = 'aamovement_session_v2';
export const BACKEND_TOKEN_COOKIE_NAME = 'aamovement_backend_token';
export const SESSION_MAX_AGE = 60 * 60 * 24;

export function hashPin(pin: string, salt: string = 'adc-2027-presidential-salt-v2'): string {
  return sha256(`${salt}:${pin}:${salt}`);
}

export function getAuthenticatedHome(user: Pick<UserSession, 'role'>): string {
  return user.role === 'PU_AGENT' ? '/agent' : '/dashboard';
}

function encode(bytes: Uint8Array): string {
  return btoa(Array.from(bytes, (byte) => String.fromCharCode(byte)).join(''))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

function decode(value: string): Uint8Array<ArrayBuffer> {
  return Uint8Array.from(atob(value.replace(/-/g, '+').replace(/_/g, '/')), (char) => char.charCodeAt(0));
}

export class SessionConfigurationError extends Error {}

async function signingKey() {
  const runtimeSecret = process.env.AUTH_SESSION_SECRET;
  const secret = runtimeSecret && runtimeSecret.length >= 32 ? runtimeSecret : process.env.BUILD_AUTH_SESSION_SECRET;
  if (!secret || secret.length < 32) {
    throw new SessionConfigurationError('AUTH_SESSION_SECRET must be configured with at least 32 characters.');
  }
  return crypto.subtle.importKey(
    'raw', new TextEncoder().encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign', 'verify']
  );
}

export async function createSessionToken(user: UserSession, backendToken: string): Promise<string> {
  const payload = encode(new TextEncoder().encode(JSON.stringify({
    user,
    backendTokenHash: sha256(backendToken),
    exp: Date.now() + SESSION_MAX_AGE * 1000,
  })));
  const signature = await crypto.subtle.sign('HMAC', await signingKey(), new TextEncoder().encode(payload));
  return `${payload}.${encode(new Uint8Array(signature))}`;
}

const roles: UserRole[] = [
  'PU_AGENT', 'WARD_SUPERVISOR', 'LGA_SUPERVISOR', 'STATE_SUPERVISOR',
  'REGIONAL_COORDINATOR', 'NATIONAL_COORDINATOR', 'GETOCORE_TECH_SUPPORT',
];

export async function parseSessionToken(token?: string, backendToken?: string): Promise<UserSession | null> {
  if (!token || !backendToken) return null;
  const key = await signingKey();
  try {
    const parts = token.split('.');
    if (parts.length !== 2) return null;
    const [payload, signature] = parts;
    if (!await crypto.subtle.verify('HMAC', key, decode(signature), new TextEncoder().encode(payload))) {
      return null;
    }
    const data = JSON.parse(new TextDecoder().decode(decode(payload)));
    const user = data?.user;
    if (typeof data.exp !== 'number' || !Number.isFinite(data.exp) || Date.now() >= data.exp ||
        data.backendTokenHash !== sha256(backendToken) || !user ||
        !roles.includes(user.role) ||
        !['PU', 'WARD', 'LGA', 'STATE', 'REGION', 'NATIONAL'].includes(user.assigned_scope_type) ||
        !['id', 'full_name', 'phone_number', 'assigned_scope_id', 'auth_identifier']
          .every((field) => typeof user[field] === 'string' && user[field].length > 0)) {
      return null;
    }
    return user;
  } catch {
    // Malformed or tampered cookies are unauthenticated.
    return null;
  }
}
