import 'dotenv/config';
import express, { NextFunction, Request, Response } from "express";
import cors from "cors";
// import bodyParser from "body-parser";
import multer from "multer";
import path from "path";
import fs from "fs";
import { db } from '@/src/db/db_index';
import { staffUsers, userDetails } from '@/src/db/schema';
import { eq } from 'drizzle-orm';
import mainRouter from '@/src/main-router';
import initFunc from '@/src/lib/init';
import { createExpressMiddleware } from '@trpc/server/adapters/express';
import { appRouter } from '@/src/trpc/router';
import { TRPCError } from '@trpc/server';
import jwt from 'jsonwebtoken'
import signedUrlCache from '@/src/lib/signed-url-cache';
import { seed } from '@/src/db/seed';
import '@/src/jobs/jobs-index';
import { startAutomatedJobs } from '@/src/lib/automatedJobs';

seed()
initFunc()
startAutomatedJobs()

const app = express();

app.use(cors({
  origin: 'http://localhost:5174' 
}));


signedUrlCache.loadFromDisk();

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Middleware to log all request URLs
app.use((req, res, next) => {
  const timestamp = new Date().toISOString();
  console.log(`[${timestamp}] ${req.method} ${req.url}`);
  next();
});

//cors middleware
export function corsMiddleware(req: Request, res: Response, next: NextFunction) {
  // Allow requests from any origin (for production, replace * with your domain)
  res.header('Access-Control-Allow-Origin', '*');

  // Allow specific headers clients can send
  res.header(
    'Access-Control-Allow-Headers',
    'Origin, X-Requested-With, Content-Type, Accept, Authorization'
  );

  // Allow specific HTTP methods
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');

  // Allow credentials if needed (optional)
  // res.header('Access-Control-Allow-Credentials', 'true');

  // Handle preflight (OPTIONS) requests quickly
  if (req.method === 'OPTIONS') {
    return res.sendStatus(204);
  }

  next();
}


app.use('/api/trpc', createExpressMiddleware({
  router: appRouter,
  createContext: async ({ req, res }) => {
    let user = null;
    let staffUser = null;
    const authHeader = req.headers.authorization;
    
    if (authHeader?.startsWith('Bearer ')) {
      const token = authHeader.substring(7);
      try {
        const decoded = jwt.verify(token, process.env.JWT_SECRET || 'your-secret-key') as any;
        
        // Check if this is a staff token (has staffId)
        if (decoded.staffId) {
          // This is a staff token, verify staff exists
          const staff = await db.query.staffUsers.findFirst({
            where: eq(staffUsers.id, decoded.staffId),
          });

          if (staff) {
            user=staffUser
            staffUser = {
              id: staff.id,
              name: staff.name,
            };
          }
        } else {
          
          // This is a regular user token
          user = decoded;

          // Check if user is suspended
          const details = await db.query.userDetails.findFirst({
            where: eq(userDetails.userId, user.userId),
          });

          if (details?.isSuspended) {
            throw new TRPCError({
              code: 'FORBIDDEN',
              message: 'Account suspended',
            });
          }
        }
      } catch (err) {
        // Invalid token, both user and staffUser remain null
      }
    }
    return { req, res, user, staffUser };
  },
  onError({ error, path, type, ctx }) {
  console.error('🚨 tRPC Error :', {
    path,
    type,
    code: error.code,
    message: error.message,
    userId: ctx?.user?.userId,
    stack: error.stack,
  });
},
}));

app.use('/api', mainRouter)

const fallbackUiDirCandidates = [
  path.resolve(__dirname, '../fallback-ui/dist'),
  path.resolve(__dirname, '../../fallback-ui/dist'),
  path.resolve(process.cwd(), '../fallback-ui/dist'),
  path.resolve(process.cwd(), './apps/fallback-ui/dist')
]

const fallbackUiDir =
  fallbackUiDirCandidates.find((candidate) => fs.existsSync(candidate)) ??
  fallbackUiDirCandidates[0]


const fallbackUiIndex = path.join(fallbackUiDir, 'index.html')
// const fallbackUiMountPath = '/admin-web'
const fallbackUiMountPath = '/';

if (fs.existsSync(fallbackUiIndex)) {
  app.use(fallbackUiMountPath, express.static(fallbackUiDir))
  app.use('/mf'+fallbackUiMountPath, express.static(fallbackUiDir))
  const fallbackUiRegex = new RegExp(
    `^${fallbackUiMountPath.replace(/\//g, '\\/')}(?:\\/.*)?$`
  )
  app.get([fallbackUiMountPath, fallbackUiRegex], (req, res) => {
    res.sendFile(fallbackUiIndex)
  })
  app.get(/.*/, (req,res) => {
    res.sendFile(fallbackUiIndex)
  })
} else {
  console.warn(`Fallback UI build not found at ${fallbackUiIndex}`)
}

// Serve /assets/public folder at /assets route
const assetsPublicDir = path.resolve(__dirname, './assets/public');
if (fs.existsSync(assetsPublicDir)) {
  app.use('/assets', express.static(assetsPublicDir));
  console.log('Serving /assets from', assetsPublicDir);
} else {
  console.warn('Assets public folder not found at', assetsPublicDir);
}

// Global error handler
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
  console.error(err);
  const status = err.statusCode || err.status || 500;
  const message = err.message || 'Internal Server Error';
  res.status(status).json({ message });
});

app.listen(4000, () => {
  console.log("Server is running on http://localhost:4000/api/mobile/");
});
