import { NextResponse, type NextRequest } from 'next/server';
import { jwtVerify } from 'jose';

const JWT_SECRET_RAW = process.env.JWT_SECRET;
const DEFAULT_SECRET = 'restroagent-dev-secret-key-not-for-production';
const USING_DEFAULT_SECRET = !JWT_SECRET_RAW;

if (USING_DEFAULT_SECRET && process.env.NODE_ENV === 'production') {
  console.error(
    '[RestroAgent] FATAL: JWT_SECRET is not set. ' +
    'All dashboard requests will be rejected until you add JWT_SECRET to your .env file.'
  );
}

const JWT_SECRET = new TextEncoder().encode(JWT_SECRET_RAW || DEFAULT_SECRET);
const COOKIE_NAME = 'restroagent_session';
const SUB_GATE_COOKIE = 'sub_gate';

const PUBLIC_PATHS = [
  '/login',
  '/register',
  '/forgot-password',
  '/reset-password',
  '/demo-setup',
  '/home-landing',
  '/about',
  '/blog',
  '/contact',
  '/faq',
  '/pricing',
  '/terms',
  '/privacy',
  '/cookie',
  '/refund',
  '/api/',
  '/auth/',
  '/tts-audio/',
];

const TRIAL_GATE_EXEMPT = ['/billing', '/onboarding', '/sign-out', '/logout'];

function isPublicPath(pathname: string): boolean {
  if (pathname === '/') return true;
  return PUBLIC_PATHS.some(p => pathname.startsWith(p));
}

function isTrialGateExempt(pathname: string): boolean {
  return TRIAL_GATE_EXEMPT.some(p => pathname.startsWith(p));
}

export async function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl;

  if (isPublicPath(pathname)) {
    return NextResponse.next();
  }

  if (USING_DEFAULT_SECRET && process.env.NODE_ENV === 'production') {
    const url = request.nextUrl.clone();
    url.pathname = '/login';
    return NextResponse.redirect(url);
  }

  const token = request.cookies.get(COOKIE_NAME)?.value;
  if (!token) {
    const url = request.nextUrl.clone();
    url.pathname = '/login';
    return NextResponse.redirect(url);
  }

  let session: { role?: string } | null = null;
  try {
    const { payload } = await jwtVerify(token, JWT_SECRET);
    session = payload as { role?: string };
  } catch {
    const url = request.nextUrl.clone();
    url.pathname = '/login';
    return NextResponse.redirect(url);
  }

  const role = session?.role;
  const isAdmin = role === 'superadmin' || role === 'support';

  if (!isAdmin && !isTrialGateExempt(pathname)) {
    const cachedGate = request.cookies.get(SUB_GATE_COOKIE)?.value;
    let gateValue = cachedGate;

    if (!gateValue) {
      try {
        const gateUrl = new URL('/api/auth/gate', request.url);
        const gateRes = await fetch(gateUrl.toString(), {
          headers: { cookie: request.headers.get('cookie') || '' },
        });
        if (gateRes.ok) {
          const data = (await gateRes.json()) as { gate: string };
          gateValue = data.gate;
        } else {
          gateValue = 'inactive';
        }
      } catch {
        gateValue = 'inactive';
      }
      const response = gateValue === 'expired' || gateValue === 'inactive'
        ? (() => {
            const url = request.nextUrl.clone();
            url.pathname = '/billing';
            url.search = '?reason=trial_expired';
            return NextResponse.redirect(url);
          })()
        : NextResponse.next();
      response.cookies.set(SUB_GATE_COOKIE, gateValue, {
        httpOnly: true,
        sameSite: 'lax',
        path: '/',
        maxAge: 300,
        secure: process.env.NODE_ENV === 'production',
      });
      return response;
    } else if (gateValue === 'expired' || gateValue === 'inactive') {
      const url = request.nextUrl.clone();
      url.pathname = '/billing';
      url.search = '?reason=trial_expired';
      return NextResponse.redirect(url);
    }
  }

  return NextResponse.next();
}

export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico|tts-audio/|.*\\.(?:svg|png|jpg|jpeg|gif|webp|wav|mp3)$).*)'],
};
