import { Request, Response, NextFunction } from 'express';
import { LegalService } from '../services/legal.service';
import { AuthRequest } from '../middleware/auth.middleware';
import { DocumentType } from '@prisma/client';
import { z } from 'zod';

const docSchema = z.object({
  type: z.enum(['NDA', 'MSA']),
  version: z.string(),
  content: z.string().min(1),
  pdfUrl: z.string().optional().nullable(),
});

export class LegalController {
  private legalService = new LegalService();

  public create = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = docSchema.parse(req.body);
      const doc = await this.legalService.createDocument(data as any);
      res.status(201).json(doc);
    } catch(err) { next(err); }
  }

  public getActive = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const type = req.params.type.toUpperCase() as DocumentType;
      const userId = (req as any).user?.userId;
      const doc = await this.legalService.getActiveDocument(type, userId);
      if (!doc) {
        if (userId) {
          return res.status(200).json({ skipped: true });
        }
        return res.status(404).json({ error: 'No active document found' });
      }
      res.status(200).json(doc);
    } catch(err) { next(err); }
  }

  public accept = async (req: AuthRequest, res: Response, next: NextFunction) => {
    try {
      const { docId } = req.body;
      const userId = req.user!.userId;
      const ipAddress = req.ip || req.socket.remoteAddress || 'unknown';

      const acceptance = await this.legalService.recordAcceptance(docId, userId, ipAddress);
      res.status(201).json(acceptance);
    } catch(err) { next(err); }
  }

  public sign = async (req: AuthRequest, res: Response, next: NextFunction) => {
    try {
      const { documentType, signatureBase64, documentUrl } = req.body;
      const userId = req.user!.userId;
      const ipAddress = req.ip || req.socket.remoteAddress || 'unknown';

      if (!signatureBase64 && !documentUrl) {
        return res.status(400).json({ error: 'Must provide either signatureBase64 or documentUrl' });
      }

      // Get active document for this type
      const type = documentType.toUpperCase() as DocumentType;
      const activeDoc = await this.legalService.getActiveDocument(type, userId);
      
      if (!activeDoc) {
        return res.status(404).json({ error: 'No active document found to sign' });
      }

      // Hash the signature if provided
      let signatureHash = null;
      if (signatureBase64) {
        const crypto = require('crypto');
        signatureHash = crypto.createHash('sha256').update(signatureBase64).digest('hex');
      }

      const acceptance = await this.legalService.recordAcceptance(
        activeDoc.id, 
        userId, 
        ipAddress, 
        signatureHash || undefined, 
        documentUrl,
        signatureBase64 || undefined
      );
      
      // Check if they completed all onboarding steps
      await this.legalService.checkOnboardingCompletion(userId);

      res.status(201).json(acceptance);
    } catch(err) { next(err); }
  }

  public myAcceptances = async (req: AuthRequest, res: Response, next: NextFunction) => {
    try {
      const acceptances = await this.legalService.getAcceptances(req.user!.userId);
      res.status(200).json(acceptances);
    } catch(err) { next(err); }
  }

  public getPending = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const pending = await this.legalService.getPendingApprovals();
      res.status(200).json(pending);
    } catch(err) { next(err); }
  }

  public approvePartner = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const { partnerId } = req.params;
      await this.legalService.approvePartner(partnerId);
      res.status(200).json({ message: 'Partner approved successfully' });
    } catch(err) { next(err); }
  }

  public listAll = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const docs = await this.legalService.getAllDocuments();
      res.status(200).json(docs);
    } catch(err) { next(err); }
  }

  public uploadSignedDoc = async (req: AuthRequest, res: Response, next: NextFunction) => {
    try {
      if (!req.file) throw new Error('No file uploaded');
      res.status(200).json({ url: `/uploads/${req.file.filename}` });
    } catch (err) { next(err); }
  }
}
