/**
 * Wikipedia Profile Routes
 *
 * CRUD + AI generation for Wikipedia-style profiles.
 */

import express, { Request, Response } from 'express';
import { body, validationResult } from 'express-validator';
import path from 'path';
import fs from 'fs';
import { getModels } from '../models';
import { authenticateJwtOrApiToken } from '../middleware/dualAuth';
import { requireCompanyAccess } from '../middleware/auth';
import { requirePermission } from '../middleware/permissions';
import { generateWithAI } from '../utils/aiProvider';
import { uploadSingle } from '../middleware/upload';
import { createJob, updateJobProgress, completeJob, failJob, getJob } from '../services/aiContext/aiJobManager';

const router = express.Router();

// Auth middleware
router.use(authenticateJwtOrApiToken);

// Ensure uploads directory for wikipedia signatures exists
const signaturesDir = path.join(process.cwd(), 'uploads', 'wikipedia-signatures');
if (!fs.existsSync(signaturesDir)) {
  fs.mkdirSync(signaturesDir, { recursive: true });
}

// ============================================
// VALIDATION
// ============================================

const createValidation = [
  body('companyId').isString().notEmpty().withMessage('Company ID is required'),
  body('profileType').isIn(['company', 'founder', 'employee']).withMessage('Invalid profile type'),
  body('profileName').isString().notEmpty().withMessage('Profile name is required').trim().isLength({ max: 300 }),
  body('businessProfileId').optional().isString(),
  body('founderId').optional().isString(),
  body('employeeId').optional().isString(),
  body('language').optional().isString(),
  body('prompt').optional().isString(),
  body('profileData').isObject().withMessage('Profile data is required'),
];

const updateValidation = [
  body('profileName').optional().isString().notEmpty().trim().isLength({ max: 300 }),
  body('language').optional().isString(),
  body('prompt').optional().isString(),
  body('profileData').optional().isObject(),
];

// ============================================
// AI PROMPT BUILDERS
// ============================================

function buildCompanyPrompt(businessProfile: any, language: string, userPrompt?: string): string {
  const bp = businessProfile;
  const parts: string[] = [];

  parts.push('You are a Wikipedia-style information specialist. Generate a structured Wikipedia-style company profile (infobox format) using ONLY the data provided below. Do NOT fabricate or invent any information.');

  parts.push('\n## RULES');
  parts.push('- Generate ONLY structured Wikipedia-style profile information (infobox format).');
  parts.push('- Do NOT generate company history, long descriptions, articles, references, external links, or table of contents.');
  parts.push('- If information is unavailable, leave the field empty or use "Not Available".');
  parts.push('- Use the exact field names provided in the JSON schema.');
  parts.push('- Be factual and concise. No marketing language.');
  parts.push('- Generate the profile in ' + language + '.');

  if (userPrompt) {
    parts.push('\n## ADDITIONAL INSTRUCTIONS\n' + userPrompt);
  }

  parts.push('\n## BUSINESS PROFILE DATA');
  if (bp.name) parts.push('Company Name: ' + bp.name);
  if (bp.description) parts.push('Description: ' + bp.description);
  if (bp.descriptionLong) parts.push('Full Description: ' + bp.descriptionLong);
  if (bp.primaryIndustry) parts.push('Industry: ' + bp.primaryIndustry);
  if (bp.secondaryIndustries) parts.push('Secondary Industries: ' + bp.secondaryIndustries);
  if (bp.businessModel) parts.push('Business Model: ' + bp.businessModel);
  if (bp.startDate) parts.push('Founded: ' + bp.startDate);
  if (bp.stage) parts.push('Stage: ' + bp.stage);
  if (bp.teamSize) parts.push('Number of Employees: ' + bp.teamSize);
  if (bp.mission) parts.push('Mission: ' + bp.mission);
  if (bp.vision) parts.push('Vision: ' + bp.vision);
  if (bp.coreValues) parts.push('Core Values: ' + bp.coreValues);
  if (bp.usp) parts.push('USP: ' + bp.usp);
  if (bp.primaryOffering) parts.push('Primary Offering: ' + bp.primaryOffering);
  if (bp.secondaryOfferings) parts.push('Secondary Offerings: ' + bp.secondaryOfferings);
  if (bp.targetGeography) parts.push('Area Served: ' + bp.targetGeography);
  if (bp.funding) parts.push('Funding: ' + bp.funding);
  if (bp.revenue) parts.push('Revenue: ' + bp.revenue);
  if (bp.email) parts.push('Email: ' + bp.email);
  if (bp.phone) parts.push('Phone: ' + bp.phone);
  if (bp.website) parts.push('Website: ' + bp.website);
  if (bp.address || bp.city || bp.state || bp.country) {
    const addressParts = [bp.address, bp.city, bp.state, bp.country].filter(Boolean).join(', ');
    parts.push('Headquarters: ' + addressParts);
  }
  if (bp.socialProfiles) {
    if (bp.socialProfiles.linkedIn) parts.push('LinkedIn: ' + bp.socialProfiles.linkedIn);
    if (bp.socialProfiles.twitter) parts.push('Twitter: ' + bp.socialProfiles.twitter);
    if (bp.socialProfiles.instagram) parts.push('Instagram: ' + bp.socialProfiles.instagram);
    if (bp.socialProfiles.facebook) parts.push('Facebook: ' + bp.socialProfiles.facebook);
    if (bp.socialProfiles.youTube) parts.push('YouTube: ' + bp.socialProfiles.youTube);
  }

  parts.push('\n## REQUIRED OUTPUT FORMAT');
  parts.push('Return ONLY valid JSON matching this exact schema:');
  parts.push(JSON.stringify({
    companyName: 'string',
    nativeName: 'string (leave empty if not available)',
    logo: 'string (leave empty)',
    companyType: 'string (e.g. Private, Public, etc.)',
    industry: 'string',
    founded: 'string (year or date)',
    founder: 'string (founder names)',
    headquarters: 'string (city, country)',
    areaServed: 'string',
    keyPeople: 'string (names and titles)',
    numberOfEmployees: 'string',
    products: 'string (comma-separated)',
    services: 'string (comma-separated)',
    brands: 'string (comma-separated)',
    parentOrganization: 'string',
    subsidiaries: 'string (comma-separated)',
    website: 'string',
    socialLinks: {
      linkedIn: 'string',
      twitter: 'string',
      instagram: 'string',
      facebook: 'string',
      youtube: 'string',
      other: 'string',
    },
    mission: 'string',
    vision: 'string',
    description: 'string (brief 1-2 sentence summary)',
    revenue: 'string',
    funding: 'string',
    businessModel: 'string',
    targetGeography: 'string',
    coreValues: 'string',
    usp: 'string',
    primaryOffering: 'string',
    email: 'string',
    phone: 'string',
    address: 'string',
  }, null, 2));

  return parts.join('\n');
}

function buildFounderPrompt(businessProfile: any, founder: any, language: string, userPrompt?: string): string {
  const bp = businessProfile;
  const f = founder;
  const parts: string[] = [];

  parts.push('You are a Wikipedia-style information specialist. Generate a structured Wikipedia-style founder profile (infobox format) using ONLY the data provided below. Do NOT fabricate or invent any information.');

  parts.push('\n## RULES');
  parts.push('- Generate ONLY structured Wikipedia-style profile information (infobox format).');
  parts.push('- Do NOT generate biography paragraphs, long descriptions, references, external links, or table of contents.');
  parts.push('- If information is unavailable, leave the field empty or use "Not Available".');
  parts.push('- Use the exact field names provided in the JSON schema.');
  parts.push('- Be factual and concise. No marketing language.');
  parts.push('- Company-related fields MUST come from the Business Profile data.');
  parts.push('- The "born" field MUST be a JSON object with keys: dateOfBirth and birthPlace only. Leave dateOfBirth empty — it will be auto-populated from the founder\'s date of birth. Leave birthPlace empty unless you have specific knowledge of the person\'s actual birth place — do NOT infer birthPlace from the person\'s current city, state, or country. Do NOT include fullName or age in born.');
  parts.push('- Generate the profile in ' + language + '.');

  if (userPrompt) {
    parts.push('\n## ADDITIONAL INSTRUCTIONS\n' + userPrompt);
  }

  parts.push('\n## FOUNDER DATA');
  if (f.name) parts.push('Full Name: ' + f.name);
  if (f.designation) parts.push('Designation/Position: ' + f.designation);
  if (f.email) parts.push('Email: ' + f.email);
  if (f.phone) parts.push('Phone: ' + f.phone);
  if (f.city || f.state || f.country) {
    parts.push('Current Location: ' + [f.city, f.state, f.country].filter(Boolean).join(', '));
  }
  if (f.dateOfBirth) parts.push('Date of Birth: ' + f.dateOfBirth);
  if (f.workAnniversary) parts.push('Work Anniversary: ' + f.workAnniversary);
  if (f.expertise && f.expertise.length > 0) parts.push('Expertise: ' + f.expertise.join(', '));
  if (f.responsibilityArea) parts.push('Responsibility Area: ' + f.responsibilityArea);
  if (f.bio) parts.push('Bio: ' + f.bio);
  if (f.socialProfiles) {
    if (f.socialProfiles.linkedIn) parts.push('LinkedIn: ' + f.socialProfiles.linkedIn);
    if (f.socialProfiles.twitter) parts.push('Twitter: ' + f.socialProfiles.twitter);
    if (f.socialProfiles.instagram) parts.push('Instagram: ' + f.socialProfiles.instagram);
    if (f.socialProfiles.facebook) parts.push('Facebook: ' + f.socialProfiles.facebook);
    if (f.socialProfiles.website) parts.push('Website: ' + f.socialProfiles.website);
  }

  parts.push('\n## BUSINESS PROFILE DATA (company context)');
  if (bp.name) parts.push('Company Name: ' + bp.name);
  if (bp.primaryIndustry) parts.push('Industry: ' + bp.primaryIndustry);
  if (bp.startDate) parts.push('Company Founded: ' + bp.startDate);
  if (bp.website) parts.push('Company Website: ' + bp.website);

  parts.push('\n## REQUIRED OUTPUT FORMAT');
  parts.push('Return ONLY valid JSON matching this exact schema:');
  parts.push(JSON.stringify({
    fullName: 'string',
    nativeName: 'string (leave empty if not available)',
    born: {
      dateOfBirth: 'string (leave empty — auto-populated from source data)',
      birthPlace: 'string (leave empty if not known — do NOT infer from current location)',
    },
    nationality: 'string',
    citizenship: 'string (leave empty if not available)',
    residence: 'string (current city, country)',
    occupation: 'string',
    position: 'string (current designation/position)',
    organization: 'string (company name from Business Profile)',
    knownFor: 'string (what they are known for)',
    spouse: 'string (leave empty if not available)',
    children: 'string (leave empty if not available)',
    parents: 'string (leave empty if not available)',
    siblings: 'string (leave empty if not available)',
    education: 'string (brief summary)',
    almaMater: 'string (university/school name, leave empty if not available)',
    qualifications: 'string (degrees, leave empty if not available)',
    experience: 'string (brief career summary)',
    previousOrganizations: 'string (comma-separated past companies)',
    currentOrganization: 'string (current company name)',
    awards: 'string (leave empty if not available)',
    honors: 'string (leave empty if not available)',
    recognitions: 'string (leave empty if not available)',
    website: 'string',
    socialProfiles: {
      linkedIn: 'string',
      twitter: 'string',
      instagram: 'string',
      facebook: 'string',
      youtube: 'string',
      other: 'string',
    },
    email: 'string',
    phone: 'string',
    city: 'string',
    country: 'string',
    expertise: 'string (comma-separated)',
    bio: 'string (brief 1-2 sentence summary)',
  }, null, 2));

  return parts.join('\n');
}

function buildEmployeePrompt(businessProfile: any, employee: any, language: string, userPrompt?: string): string {
  const bp = businessProfile;
  const e = employee;
  const parts: string[] = [];

  parts.push('You are a Wikipedia-style information specialist. Generate a structured Wikipedia-style employee profile (infobox format) using ONLY the data provided below. Do NOT fabricate or invent any information.');

  parts.push('\n## RULES');
  parts.push('- Generate ONLY structured Wikipedia-style profile information (infobox format).');
  parts.push('- Do NOT generate biography paragraphs, long descriptions, references, external links, or table of contents.');
  parts.push('- If information is unavailable, leave the field empty or use "Not Available".');
  parts.push('- Use the exact field names provided in the JSON schema.');
  parts.push('- Be factual and concise. No marketing language.');
  parts.push('- Company-related fields MUST come from the Business Profile data.');
  parts.push('- The "born" field MUST be a JSON object with keys: dateOfBirth and birthPlace only. Leave dateOfBirth empty — it will be auto-populated from the employee\'s date of birth. Leave birthPlace empty unless you have specific knowledge of the person\'s actual birth place — do NOT infer birthPlace from the person\'s current city, state, or country. Do NOT include fullName or age in born.');
  parts.push('- Generate the profile in ' + language + '.');

  if (userPrompt) {
    parts.push('\n## ADDITIONAL INSTRUCTIONS\n' + userPrompt);
  }

  parts.push('\n## EMPLOYEE DATA');
  if (e.name) parts.push('Full Name: ' + e.name);
  if (e.designation) parts.push('Designation: ' + e.designation);
  if (e.department) parts.push('Department: ' + e.department);
  if (e.level) parts.push('Level: ' + e.level);
  if (e.email) parts.push('Email: ' + e.email);
  if (e.phone) parts.push('Phone: ' + e.phone);
  if (e.city || e.state || e.country) {
    parts.push('Current Location: ' + [e.city, e.state, e.country].filter(Boolean).join(', '));
  }
  if (e.dateOfBirth) parts.push('Date of Birth: ' + e.dateOfBirth);
  if (e.workAnniversary) parts.push('Work Anniversary: ' + e.workAnniversary);
  if (e.expertise && e.expertise.length > 0) parts.push('Expertise: ' + e.expertise.join(', '));
  if (e.responsibilityArea) parts.push('Responsibility Area: ' + e.responsibilityArea);
  if (e.reportsTo) parts.push('Reports To: ' + e.reportsTo);
  if (e.bio) parts.push('Bio: ' + e.bio);
  if (e.socialProfiles) {
    if (e.socialProfiles.linkedIn) parts.push('LinkedIn: ' + e.socialProfiles.linkedIn);
    if (e.socialProfiles.website) parts.push('Website: ' + e.socialProfiles.website);
  }

  parts.push('\n## BUSINESS PROFILE DATA (company context)');
  if (bp.name) parts.push('Company Name: ' + bp.name);
  if (bp.primaryIndustry) parts.push('Industry: ' + bp.primaryIndustry);
  if (bp.website) parts.push('Company Website: ' + bp.website);
  if (bp.address || bp.city || bp.country) {
    parts.push('Company Address: ' + [bp.address, bp.city, bp.country].filter(Boolean).join(', '));
  }

  parts.push('\n## REQUIRED OUTPUT FORMAT');
  parts.push('Return ONLY valid JSON matching this exact schema:');
  parts.push(JSON.stringify({
    fullName: 'string',
    born: {
      dateOfBirth: 'string (leave empty — auto-populated from source data)',
      birthPlace: 'string (leave empty if not known — do NOT infer from current location)',
    },
    nationality: 'string (leave empty if not available)',
    citizenship: 'string (leave empty if not available)',
    residence: 'string (current city, country)',
    employeeId: 'string (leave empty if not available)',
    organization: 'string (company name from Business Profile)',
    department: 'string',
    designation: 'string',
    employmentType: 'string (e.g. Full-time, Part-time, Contract)',
    reportingManager: 'string (name of reporting manager, leave empty if not available)',
    joiningDate: 'string',
    experience: 'string',
    education: 'string (leave empty if not available)',
    almaMater: 'string (leave empty if not available)',
    certifications: 'string (leave empty if not available)',
    spouse: 'string (leave empty if not available)',
    children: 'string (leave empty if not available)',
    parents: 'string (leave empty if not available)',
    skills: 'string (comma-separated)',
    awards: 'string (leave empty if not available)',
    honors: 'string (leave empty if not available)',
    officeLocation: 'string',
    workEmail: 'string',
    linkedIn: 'string',
    website: 'string',
    phone: 'string',
    city: 'string',
    country: 'string',
    expertise: 'string (comma-separated)',
    bio: 'string (brief 1-2 sentence summary)',
  }, null, 2));

  return parts.join('\n');
}

// ============================================
// ROUTES
// ============================================

/**
 * GET /:companyId — List all Wikipedia profiles for a company
 */
router.get('/:companyId', requireCompanyAccess, async (req: Request, res: Response) => {
  try {
    const { WikipediaProfile } = getModels();
    const { companyId } = req.params;
    const {
      page = 1,
      limit = 20,
      search,
      profileType,
      businessProfileId,
      language,
      sortBy = 'createdAt',
      sortOrder = 'desc',
    } = req.query;

    const filter: any = { companyId };
    if (profileType) filter.profileType = profileType;
    if (businessProfileId) filter.businessProfileId = businessProfileId;
    if (language) filter.language = language;

    if (search) {
      filter.$or = [
        { profileName: { $regex: search, $options: 'i' } },
      ];
    }

    const pageNum = Math.max(1, Number(page));
    const limitNum = Math.min(100, Math.max(1, Number(limit)));
    const skip = (pageNum - 1) * limitNum;

    const sortDir = sortOrder === 'asc' ? 1 : -1;
    const sort: any = { [sortBy as string]: sortDir };

    const [profiles, total] = await Promise.all([
      WikipediaProfile.find(filter).sort(sort).skip(skip).limit(limitNum).lean(),
      WikipediaProfile.countDocuments(filter),
    ]);

    const result = profiles.map((p: any) => ({
      ...p,
      id: p._id?.toString?.() || p._id,
    }));

    res.json({
      data: result,
      total,
      page: pageNum,
      totalPages: Math.ceil(total / limitNum),
    });
  } catch (error: any) {
    console.error('[WikipediaProfile] List error:', error);
    res.status(500).json({ error: 'Failed to fetch Wikipedia profiles' });
  }
});

/**
 * GET /detail/:id — Get a single Wikipedia profile by ID
 */
router.get('/detail/:id', async (req: Request, res: Response) => {
  try {
    const { WikipediaProfile } = getModels();
    const { id } = req.params;
    const profile = await WikipediaProfile.findById(id).lean();
    if (!profile) {
      return res.status(404).json({ error: 'Wikipedia profile not found' });
    }
    res.json({
      data: {
        ...profile,
        id: profile._id?.toString?.() || profile._id,
      },
    });
  } catch (error: any) {
    console.error('[WikipediaProfile] Get error:', error);
    res.status(500).json({ error: 'Failed to fetch Wikipedia profile' });
  }
});

/**
 * POST / — Create a new Wikipedia profile
 */
router.post('/', requirePermission('wikipedia-profile', 'create'), createValidation, async (req: Request, res: Response) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
  }

  try {
    const { WikipediaProfile } = getModels();
    const user = (req as any).user;
    const profile = await WikipediaProfile.create({
      ...req.body,
      createdBy: user?.userId || user?.id || 'unknown',
    });

    res.status(201).json({
      data: {
        ...profile.toObject(),
        id: profile._id?.toString?.() || profile._id,
      },
    });
  } catch (error: any) {
    console.error('[WikipediaProfile] Create error:', error);
    res.status(500).json({ error: 'Failed to create Wikipedia profile' });
  }
});

/**
 * PUT /:id — Update a Wikipedia profile (supports partial profileData merge)
 */
router.put('/:id', requirePermission('wikipedia-profile', 'edit'), updateValidation, async (req: Request, res: Response) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
  }

  try {
    const { WikipediaProfile } = getModels();
    const { id } = req.params;

    // If profileData is being updated, merge it with existing data
    if (req.body.profileData) {
      const existing = await WikipediaProfile.findById(id).lean();
      if (!existing) {
        return res.status(404).json({ error: 'Wikipedia profile not found' });
      }
      const existingData = existing.profileData?.toObject?.() || existing.profileData || {};
      req.body.profileData = { ...existingData, ...req.body.profileData };
    }

    const updated = await WikipediaProfile.findByIdAndUpdate(
      id,
      { $set: req.body },
      { new: true, runValidators: true }
    ).lean();

    if (!updated) {
      return res.status(404).json({ error: 'Wikipedia profile not found' });
    }

    res.json({
      data: {
        ...updated,
        id: updated._id?.toString?.() || updated._id,
      },
    });
  } catch (error: any) {
    console.error('[WikipediaProfile] Update error:', error);
    res.status(500).json({ error: 'Failed to update Wikipedia profile' });
  }
});

/**
 * DELETE /:id — Delete a single Wikipedia profile
 */
router.delete('/:id', requirePermission('wikipedia-profile', 'delete'), async (req: Request, res: Response) => {
  try {
    const { WikipediaProfile } = getModels();
    const { id } = req.params;
    const deleted = await WikipediaProfile.findByIdAndDelete(id);
    if (!deleted) {
      return res.status(404).json({ error: 'Wikipedia profile not found' });
    }
    res.json({ message: 'Wikipedia profile deleted successfully' });
  } catch (error: any) {
    console.error('[WikipediaProfile] Delete error:', error);
    res.status(500).json({ error: 'Failed to delete Wikipedia profile' });
  }
});

/**
 * GET /status/:jobId — poll the progress of an AI generation job.
 *
 * Mirrors the status route every other AI module exposes so the shared
 * AiJobProgressBanner / aiJobStore polling works unchanged here.
 */
router.get('/status/:jobId', async (req: Request, res: Response) => {
  const { jobId } = req.params;
  const job = getJob(jobId);

  if (!job) {
    return res.status(404).json({ error: 'Job not found' });
  }

  res.json({
    jobId: job.jobId,
    status: job.status,
    progress: job.progress,
    step: job.step,
    result: job.result,
    error: job.error,
  });
});

/**
 * POST /generate — AI-generate a Wikipedia profile
 *
 * Validation and source-data lookups stay on the response path (so bad
 * requests still get their 400/404), then an AI job is created and the
 * generation runs in the background. Returns 202 + jobId; the frontend
 * polls GET /status/:jobId for progress.
 */
router.post('/generate', authenticateJwtOrApiToken, async (req: Request, res: Response) => {
  try {
    const models = getModels();
    const { WikipediaProfile, BusinessProfile: BusinessProfileModel, Founder: FounderModel, Employee: EmployeeModel } = models;
    const user = (req as any).user;

    const {
      companyId,
      profileType,
      businessProfileId: reqBusinessProfileId,
      founderId,
      employeeId,
      language = 'English',
      prompt: userPrompt,
    } = req.body;

    if (!companyId || !profileType) {
      return res.status(400).json({ error: 'companyId and profileType are required' });
    }

    if (!['company', 'founder', 'employee'].includes(profileType)) {
      return res.status(400).json({ error: 'Invalid profileType. Must be company, founder, or employee' });
    }

    if (profileType === 'founder' && !founderId) {
      return res.status(400).json({ error: 'founderId is required for founder profile type' });
    }

    if (profileType === 'employee' && !employeeId) {
      return res.status(400).json({ error: 'employeeId is required for employee profile type' });
    }

    // Auto-select Business Profile if not provided
    let businessProfileIdToUse = reqBusinessProfileId;
    if (!businessProfileIdToUse) {
      const autoBP = await BusinessProfileModel.findOne({ companyId }).lean();
      if (autoBP) {
        businessProfileIdToUse = autoBP._id.toString();
      }
    }

    if (!businessProfileIdToUse) {
      return res.status(400).json({ error: 'Business Profile not found for this company' });
    }

    // Fetch source data
    const businessProfile = await BusinessProfileModel.findOne({ companyId, _id: businessProfileIdToUse }).lean();
    if (!businessProfile) {
      return res.status(404).json({ error: 'Business profile not found' });
    }

    let systemPrompt: string;
    let profileName: string;
    let founder: any = null;
    let employee: any = null;

    if (profileType === 'company') {
      profileName = businessProfile.name + ' — Company Profile';
      systemPrompt = buildCompanyPrompt(businessProfile, language, userPrompt);
    } else if (profileType === 'founder') {
      founder = await FounderModel.findOne({ companyId, _id: founderId }).lean();
      if (!founder) {
        return res.status(404).json({ error: 'Founder not found' });
      }
      profileName = founder.name + ' — Founder Profile';
      systemPrompt = buildFounderPrompt(businessProfile, founder, language, userPrompt);
    } else {
      employee = await EmployeeModel.findOne({ companyId, _id: employeeId }).lean();
      if (!employee) {
        return res.status(404).json({ error: 'Employee not found' });
      }
      profileName = employee.name + ' — Employee Profile';
      systemPrompt = buildEmployeePrompt(businessProfile, employee, language, userPrompt);
    }

    // Everything needed for generation is resolved — hand off to a tracked AI
    // job and return immediately so the frontend can show real progress.
    const job = createJob('wikipedia-profile', companyId, req.body._moduleId);
    res.status(202).json({ jobId: job.jobId, status: 'processing' });

    // Run the AI generation in the background (do NOT await on the response path)
    setImmediate(async () => {
      try {
        updateJobProgress(job.jobId, 20, 'Generating profile with AI...');

        // Call AI
        const aiResult = await generateWithAI(
          'Generate the Wikipedia-style profile based on the provided data.',
          systemPrompt,
          8000,
          undefined,
          'json',
          undefined,
          undefined,
          user?.userId || user?.id || 'unknown',
          companyId,
        );

        updateJobProgress(job.jobId, 70, 'Parsing generated profile...');

        // Parse the AI response as JSON
        let profileData: any;
        try {
          const responseText = aiResult.content || '';
          const jsonMatch = responseText.match(/\{[\s\S]*\}/);
          if (jsonMatch) {
            profileData = JSON.parse(jsonMatch[0]);
          } else {
            profileData = JSON.parse(responseText);
          }
        } catch (parseError) {
          console.error('[WikipediaProfile] AI response parse error:', parseError);
          failJob(job.jobId, 'Failed to parse AI-generated profile data');
          return;
        }

        // Auto-populate born.dateOfBirth from source record and remove photograph/age
        if (profileType === 'founder' && founder) {
          // Set dateOfBirth from founder's dateOfBirth
          if (founder.dateOfBirth) {
            profileData.born = { ...(typeof profileData.born === 'object' ? profileData.born : {}), dateOfBirth: founder.dateOfBirth };
          }
        }
        if (profileType === 'employee' && employee) {
          // Set dateOfBirth from employee's dateOfBirth
          if (employee.dateOfBirth) {
            profileData.born = { ...(typeof profileData.born === 'object' ? profileData.born : {}), dateOfBirth: employee.dateOfBirth };
          }
        }
        // Remove fullName and age from born if present (should not be stored)
        if (profileData.born && typeof profileData.born === 'object') {
          delete profileData.born.fullName;
          delete profileData.born.age;
        }
        // Remove photograph from profileData — it's resolved dynamically from source
        delete profileData.photograph;

        updateJobProgress(job.jobId, 90, 'Saving profile...');

        // Create the Wikipedia profile
        const newProfile = await WikipediaProfile.create({
          companyId,
          profileType,
          profileName,
          businessProfileId: businessProfileIdToUse,
          founderId: founderId || undefined,
          employeeId: employeeId || undefined,
          language,
          prompt: userPrompt || undefined,
          aiProvider: aiResult?.provider || undefined,
          aiModel: aiResult?.model || undefined,
          aiGeneratedAt: new Date(),
          profileData,
          createdBy: user?.userId || user?.id || 'unknown',
        });

        completeJob(
          job.jobId,
          {
            profileId: newProfile._id?.toString?.() || newProfile._id,
            profileName,
            profileType,
          },
          'generated',
        );
      } catch (err: any) {
        console.error(`[WikipediaProfile] Generate job ${job.jobId} failed:`, err?.message || err);
        failJob(job.jobId, err?.message || 'Failed to generate Wikipedia profile');
      }
    });
  } catch (error: any) {
    console.error('[WikipediaProfile] Generate error:', error);
    res.status(500).json({ error: error.message || 'Failed to generate Wikipedia profile' });
  }
});

/**
 * POST /:id/duplicate — Duplicate a Wikipedia profile
 */
router.post('/:id/duplicate', requirePermission('wikipedia-profile', 'create'), async (req: Request, res: Response) => {
  try {
    const { WikipediaProfile } = getModels();
    const { id } = req.params;
    const user = (req as any).user;

    const original = await WikipediaProfile.findById(id).lean();
    if (!original) {
      return res.status(404).json({ error: 'Wikipedia profile not found' });
    }

    const duplicate = await WikipediaProfile.create({
      ...original,
      _id: undefined,
      profileName: (original.profileName || 'Untitled') + ' (Copy)',
      createdBy: user?.userId || user?.id || 'unknown',
      aiGeneratedAt: undefined,
    });

    res.status(201).json({
      data: {
        ...duplicate.toObject(),
        id: duplicate._id?.toString?.() || duplicate._id,
      },
    });
  } catch (error: any) {
    console.error('[WikipediaProfile] Duplicate error:', error);
    res.status(500).json({ error: 'Failed to duplicate Wikipedia profile' });
  }
});

/**
 * POST /:id/signature — Upload signature image for a Wikipedia profile
 */
router.post('/:id/signature', authenticateJwtOrApiToken, uploadSingle.single('file'), async (req: Request, res: Response) => {
  try {
    const { WikipediaProfile } = getModels();
    const { id } = req.params;

    if (!req.file) {
      return res.status(400).json({ error: 'No file uploaded' });
    }

    const profile = await WikipediaProfile.findById(id);
    if (!profile) {
      return res.status(404).json({ error: 'Wikipedia profile not found' });
    }

    const signatureUrl = `/uploads/${req.file.filename}`;

    // Update the signature within profileData
    const existingData = profile.profileData?.toObject?.() || profile.profileData || {};
    existingData.signature = signatureUrl;

    const updated = await WikipediaProfile.findByIdAndUpdate(
      id,
      { $set: { profileData: existingData } },
      { new: true }
    ).lean();

    res.json({
      data: {
        ...updated,
        id: updated!._id?.toString?.() || updated!._id,
      },
    });
  } catch (error: any) {
    console.error('[WikipediaProfile] Signature upload error:', error);
    res.status(500).json({ error: 'Failed to upload signature' });
  }
});

/**
 * DELETE /:id/signature — Remove signature from a Wikipedia profile
 */
router.delete('/:id/signature', authenticateJwtOrApiToken, async (req: Request, res: Response) => {
  try {
    const { WikipediaProfile } = getModels();
    const { id } = req.params;

    const profile = await WikipediaProfile.findById(id);
    if (!profile) {
      return res.status(404).json({ error: 'Wikipedia profile not found' });
    }

    const existingData = profile.profileData?.toObject?.() || profile.profileData || {};
    existingData.signature = '';

    const updated = await WikipediaProfile.findByIdAndUpdate(
      id,
      { $set: { profileData: existingData } },
      { new: true }
    ).lean();

    res.json({
      data: {
        ...updated,
        id: updated!._id?.toString?.() || updated!._id,
      },
    });
  } catch (error: any) {
    console.error('[WikipediaProfile] Signature delete error:', error);
    res.status(500).json({ error: 'Failed to remove signature' });
  }
});

export default router;