/**
 * Safe Link Acquisition Agent
 * White-hat link building with human-in-the-loop approval
 *
 * CRITICAL: This agent NEVER sends outreach automatically.
 * All link opportunities require explicit human approval before any action.
 */

import { PrismaClient } from '@prisma/client';
import { ComplianceService } from '../../compliance';

const prisma = new PrismaClient();

// Opportunity types
export type OpportunityType =
  | 'haro'          // Help A Reporter Out / Connectively
  | 'guest_post'    // Guest posting (with strict filtering)
  | 'broken_link'   // Broken link building
  | 'mention'       // Unlinked brand mentions
  | 'resource_page' // Resource page link building
  | 'skyscraper';   // Skyscraper technique

// Opportunity status
export type OpportunityStatus =
  | 'pending'       // Awaiting human review
  | 'approved'      // Approved, ready for outreach
  | 'rejected'      // Rejected by human
  | 'executed'      // Outreach sent
  | 'acquired'      // Link successfully acquired
  | 'failed';       // Outreach failed

// Quality score breakdown
export interface QualityScore {
  overall: number;        // 0-100
  domainAuthority: number;
  trafficQuality: number;
  relevance: number;
  trustSignals: number;
  meetsThresholds: boolean;
  reasons: string[];
}

// Link opportunity
export interface LinkOpportunity {
  id: string;
  targetUrl: string;
  sourceDomain: string;
  domainAuthority: number;
  monthlyTraffic?: number;
  relevanceScore: number;
  opportunityType: OpportunityType;
  status: OpportunityStatus;

  // Contact info
  contactEmail?: string;
  contactName?: string;

  // Pitch
  pitchDraft: string;
  pitchApproved?: string;

  // Approval tracking
  approvedBy?: string;
  approvedAt?: Date;
  rejectionReason?: string;

  // Execution
  executedAt?: Date;
  linkAcquired: boolean;
  acquiredUrl?: string;

  // Metadata
  discoveredAt: Date;
  notes?: string;
}

// Safety configuration - strict thresholds
export const LINK_SAFETY_CONFIG = {
  // Minimum quality thresholds
  minDomainAuthority: 40,
  minMonthlyTraffic: 5000,
  minRelevanceScore: 0.8,

  // Budget caps
  maxMonthlySpend: 500,  // $500/site/month max

  // Rate limiting
  maxOutreachPerDay: 5,  // Max 5 emails per day per domain
  cooldownBetweenEmails: 3600000,  // 1 hour minimum between emails

  // Approval requirements
  requireHumanApproval: true,  // ALWAYS true - never auto-approve
  maxAutoApprovalDA: 0,        // Never auto-approve (0 means none)

  // Blacklist patterns - auto-reject any URL containing these
  blacklistPatterns: [
    'write-for-us',
    'guest-post-guidelines',
    'sponsored-post',
    'link-exchange',
    'buy-links',
    'paid-post',
    'advertise-with-us',
    'submit-guest-post',
    'link-insertion',
    'paid-content',
  ],

  // Spam indicators - flag for manual review
  spamIndicators: [
    'casino',
    'payday',
    'pharma',
    'adult',
    'gambling-affiliate',  // Note: sports betting sites are OK if legitimate
  ],
};

/**
 * Safe Link Acquisition Agent
 * Discovers white-hat link opportunities and queues for human approval
 */
export class SafeLinkAcquisitionAgent {
  private siteId?: string;
  private baseUrl: string;

  constructor(siteId?: string) {
    this.siteId = siteId;
    this.baseUrl = process.env.NEXT_PUBLIC_BASE_URL || 'https://eventheodds.ai';
  }

  /**
   * Discover white-hat link opportunities
   * Returns opportunities that meet quality thresholds
   */
  async discoverOpportunities(): Promise<LinkOpportunity[]> {
    const opportunities: LinkOpportunity[] = [];

    try {
      // 1. HARO/Connectively monitoring
      const haroOpps = await this.findHAROOpportunities();
      opportunities.push(...haroOpps);

      // 2. Unlinked brand mentions
      const mentionOpps = await this.findUnlinkedMentions();
      opportunities.push(...mentionOpps);

      // 3. Broken link building (DA 40+ only)
      const brokenOpps = await this.findBrokenLinkOpportunities();
      opportunities.push(...brokenOpps);

      // 4. Resource page opportunities
      const resourceOpps = await this.findResourcePageOpportunities();
      opportunities.push(...resourceOpps);

      await ComplianceService.log('AGENT', 'LINK_DISCOVERY_COMPLETED', 'SafeLinkAcquisitionAgent', {
        totalDiscovered: opportunities.length,
        haro: haroOpps.length,
        mentions: mentionOpps.length,
        brokenLinks: brokenOpps.length,
        resources: resourceOpps.length,
      });

    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Unknown error';
      await ComplianceService.log('AGENT', 'LINK_DISCOVERY_FAILED', 'SafeLinkAcquisitionAgent', {
        error: errorMessage,
      }, 'FAILED');
    }

    return opportunities;
  }

  /**
   * Score an opportunity against quality thresholds
   */
  async scoreOpportunity(opp: LinkOpportunity): Promise<QualityScore> {
    const reasons: string[] = [];
    let meetsThresholds = true;

    // Domain Authority score (0-30 points)
    const daScore = Math.min(30, (opp.domainAuthority / 100) * 30);
    if (opp.domainAuthority < LINK_SAFETY_CONFIG.minDomainAuthority) {
      reasons.push(`DA ${opp.domainAuthority} below threshold (min ${LINK_SAFETY_CONFIG.minDomainAuthority})`);
      meetsThresholds = false;
    }

    // Traffic quality score (0-30 points)
    const traffic = opp.monthlyTraffic || 0;
    const trafficScore = Math.min(30, (traffic / 50000) * 30);
    if (traffic < LINK_SAFETY_CONFIG.minMonthlyTraffic) {
      reasons.push(`Traffic ${traffic} below threshold (min ${LINK_SAFETY_CONFIG.minMonthlyTraffic})`);
      meetsThresholds = false;
    }

    // Relevance score (0-25 points)
    const relevanceScore = opp.relevanceScore * 25;
    if (opp.relevanceScore < LINK_SAFETY_CONFIG.minRelevanceScore) {
      reasons.push(`Relevance ${(opp.relevanceScore * 100).toFixed(0)}% below threshold (min ${LINK_SAFETY_CONFIG.minRelevanceScore * 100}%)`);
      meetsThresholds = false;
    }

    // Trust signals score (0-15 points)
    let trustScore = 15;

    // Check blacklist patterns
    const urlLower = opp.targetUrl.toLowerCase();
    const domainLower = opp.sourceDomain.toLowerCase();

    for (const pattern of LINK_SAFETY_CONFIG.blacklistPatterns) {
      if (urlLower.includes(pattern) || domainLower.includes(pattern)) {
        reasons.push(`Blacklist pattern detected: "${pattern}"`);
        meetsThresholds = false;
        trustScore = 0;
        break;
      }
    }

    // Check spam indicators
    for (const indicator of LINK_SAFETY_CONFIG.spamIndicators) {
      if (urlLower.includes(indicator) || domainLower.includes(indicator)) {
        reasons.push(`Spam indicator flagged: "${indicator}" - requires manual review`);
        trustScore = Math.max(0, trustScore - 5);
      }
    }

    const overall = Math.round(daScore + trafficScore + relevanceScore + trustScore);

    if (meetsThresholds) {
      reasons.push('Meets all quality thresholds');
    }

    return {
      overall,
      domainAuthority: Math.round(daScore),
      trafficQuality: Math.round(trafficScore),
      relevance: Math.round(relevanceScore),
      trustSignals: Math.round(trustScore),
      meetsThresholds,
      reasons,
    };
  }

  /**
   * Generate a personalized pitch for an opportunity
   * NOTE: Pitches are generated but NEVER sent automatically
   */
  async generatePitch(opp: LinkOpportunity): Promise<string> {
    // Site-specific information
    const siteInfo = {
      name: 'EventheOdds',
      description: 'free sports betting analytics platform',
      uniqueValue: 'data from over 50,000 analyzed games',
      url: this.baseUrl,
    };

    let pitch: string;

    switch (opp.opportunityType) {
      case 'haro':
        pitch = this.generateHAROPitch(opp, siteInfo);
        break;
      case 'mention':
        pitch = this.generateMentionPitch(opp, siteInfo);
        break;
      case 'broken_link':
        pitch = this.generateBrokenLinkPitch(opp, siteInfo);
        break;
      case 'resource_page':
        pitch = this.generateResourcePitch(opp, siteInfo);
        break;
      case 'guest_post':
        pitch = this.generateGuestPostPitch(opp, siteInfo);
        break;
      default:
        pitch = this.generateGenericPitch(opp, siteInfo);
    }

    await ComplianceService.log('AGENT', 'PITCH_GENERATED', 'SafeLinkAcquisitionAgent', {
      opportunityId: opp.id,
      opportunityType: opp.opportunityType,
      pitchLength: pitch.length,
    });

    return pitch;
  }

  /**
   * Queue opportunity for human approval
   * NOTE: This is the ONLY way opportunities proceed - always requires human review
   */
  async queueForApproval(opp: LinkOpportunity): Promise<string> {
    // Score the opportunity
    const score = await this.scoreOpportunity(opp);

    // Only queue if meets minimum thresholds
    if (!score.meetsThresholds) {
      await ComplianceService.log('AGENT', 'OPPORTUNITY_REJECTED_AUTO', 'SafeLinkAcquisitionAgent', {
        opportunityId: opp.id,
        reasons: score.reasons,
      });

      // Still save it but mark as rejected
      const record = await prisma.backlinkOpportunity.create({
        data: {
          siteId: this.siteId,
          targetUrl: opp.targetUrl,
          sourceDomain: opp.sourceDomain,
          domainAuthority: opp.domainAuthority,
          monthlyTraffic: opp.monthlyTraffic,
          relevanceScore: opp.relevanceScore,
          opportunityType: opp.opportunityType,
          status: 'rejected',
          rejectionReason: score.reasons.join('; '),
          pitchDraft: opp.pitchDraft,
          discoveredAt: opp.discoveredAt,
          notes: `Auto-rejected: Score ${score.overall}/100`,
        },
      });

      return record.id;
    }

    // Generate pitch if not already present
    if (!opp.pitchDraft) {
      opp.pitchDraft = await this.generatePitch(opp);
    }

    // Create pending approval record
    const record = await prisma.backlinkOpportunity.create({
      data: {
        siteId: this.siteId,
        targetUrl: opp.targetUrl,
        sourceDomain: opp.sourceDomain,
        domainAuthority: opp.domainAuthority,
        monthlyTraffic: opp.monthlyTraffic,
        relevanceScore: opp.relevanceScore,
        opportunityType: opp.opportunityType,
        status: 'pending',  // Always pending - requires human approval
        pitchDraft: opp.pitchDraft,
        contactEmail: opp.contactEmail,
        contactName: opp.contactName,
        discoveredAt: opp.discoveredAt,
        notes: `Score: ${score.overall}/100. ${score.reasons.join('; ')}`,
      },
    });

    await ComplianceService.log('AGENT', 'OPPORTUNITY_QUEUED', 'SafeLinkAcquisitionAgent', {
      opportunityId: record.id,
      opportunityType: opp.opportunityType,
      score: score.overall,
      status: 'pending_human_approval',
    });

    return record.id;
  }

  /**
   * Get pending approvals for a site
   */
  async getPendingApprovals(siteId?: string): Promise<LinkOpportunity[]> {
    const records = await prisma.backlinkOpportunity.findMany({
      where: {
        siteId: siteId || this.siteId,
        status: 'pending',
      },
      orderBy: { domainAuthority: 'desc' },
    });

    return records.map(r => ({
      id: r.id,
      targetUrl: r.targetUrl,
      sourceDomain: r.sourceDomain,
      domainAuthority: r.domainAuthority,
      monthlyTraffic: r.monthlyTraffic || undefined,
      relevanceScore: r.relevanceScore,
      opportunityType: r.opportunityType as OpportunityType,
      status: r.status as OpportunityStatus,
      contactEmail: r.contactEmail || undefined,
      contactName: r.contactName || undefined,
      pitchDraft: r.pitchDraft || '',
      pitchApproved: r.pitchApproved || undefined,
      approvedBy: r.approvedBy || undefined,
      approvedAt: r.approvedAt || undefined,
      rejectionReason: r.rejectionReason || undefined,
      executedAt: r.executedAt || undefined,
      linkAcquired: r.linkAcquired,
      acquiredUrl: r.acquiredUrl || undefined,
      discoveredAt: r.discoveredAt,
      notes: r.notes || undefined,
    }));
  }

  /**
   * Get link building statistics
   */
  async getStats(siteId?: string): Promise<{
    pending: number;
    approved: number;
    rejected: number;
    executed: number;
    acquired: number;
    averageDA: number;
  }> {
    const targetSiteId = siteId || this.siteId;

    const [pending, approved, rejected, executed, acquired] = await Promise.all([
      prisma.backlinkOpportunity.count({ where: { siteId: targetSiteId, status: 'pending' } }),
      prisma.backlinkOpportunity.count({ where: { siteId: targetSiteId, status: 'approved' } }),
      prisma.backlinkOpportunity.count({ where: { siteId: targetSiteId, status: 'rejected' } }),
      prisma.backlinkOpportunity.count({ where: { siteId: targetSiteId, status: 'executed' } }),
      prisma.backlinkOpportunity.count({ where: { siteId: targetSiteId, linkAcquired: true } }),
    ]);

    const avgDAResult = await prisma.backlinkOpportunity.aggregate({
      where: { siteId: targetSiteId, linkAcquired: true },
      _avg: { domainAuthority: true },
    });

    return {
      pending,
      approved,
      rejected,
      executed,
      acquired,
      averageDA: avgDAResult._avg.domainAuthority || 0,
    };
  }

  // ============ Discovery Methods ============

  private async findHAROOpportunities(): Promise<LinkOpportunity[]> {
    // In production, this would integrate with HARO/Connectively API
    // or a monitoring service that tracks journalist queries
    return [];
  }

  private async findUnlinkedMentions(): Promise<LinkOpportunity[]> {
    // In production, this would use a brand monitoring service
    // like Mention, Brand24, or Ahrefs alerts
    return [];
  }

  private async findBrokenLinkOpportunities(): Promise<LinkOpportunity[]> {
    // In production, this would analyze competitor backlinks
    // and find 404 pages that we could recreate
    return [];
  }

  private async findResourcePageOpportunities(): Promise<LinkOpportunity[]> {
    // In production, this would find resource/link roundup pages
    // in our niche that we could be added to
    return [];
  }

  // ============ Pitch Templates ============

  private generateHAROPitch(opp: LinkOpportunity, siteInfo: any): string {
    return `Hi ${opp.contactName || 'there'},

I saw your query and wanted to offer some insights from ${siteInfo.name}.

We're a ${siteInfo.description} that has analyzed ${siteInfo.uniqueValue}. I'd be happy to provide:

- Specific data points relevant to your article
- Expert quotes on sports betting analytics
- Any statistics you might need

Would this be helpful for your piece? I can tailor the information to your angle.

Best,
${siteInfo.name} Team`;
  }

  private generateMentionPitch(opp: LinkOpportunity, siteInfo: any): string {
    return `Hi ${opp.contactName || 'there'},

I noticed you mentioned ${siteInfo.name} in your recent article - thank you for the reference!

I wanted to reach out because I noticed the mention doesn't include a link to our site. Would you consider adding one? It would help your readers easily find the tools and data you referenced.

Our URL is: ${siteInfo.url}

Thanks for considering!

Best,
${siteInfo.name} Team`;
  }

  private generateBrokenLinkPitch(opp: LinkOpportunity, siteInfo: any): string {
    return `Hi ${opp.contactName || 'there'},

I was reading your article and noticed a broken link that might be affecting your readers' experience.

The link to [broken resource] appears to be returning a 404. We have a similar resource at ${siteInfo.name} that covers the same topic:

${siteInfo.url}/[relevant-page]

This page includes ${siteInfo.uniqueValue} and might be a helpful replacement for your readers.

Would you consider updating the link?

Best,
${siteInfo.name} Team`;
  }

  private generateResourcePitch(opp: LinkOpportunity, siteInfo: any): string {
    return `Hi ${opp.contactName || 'there'},

I came across your excellent resource page on sports betting tools and wanted to suggest an addition that your readers might find valuable.

${siteInfo.name} (${siteInfo.url}) is a ${siteInfo.description} that provides:

- Free analytics tools
- Data from ${siteInfo.uniqueValue}
- Educational content for bettors

I think it would fit well with the other resources you've curated. Would you consider adding it to your list?

Thanks for your time!

Best,
${siteInfo.name} Team`;
  }

  private generateGuestPostPitch(opp: LinkOpportunity, siteInfo: any): string {
    return `Hi ${opp.contactName || 'there'},

I'm reaching out from ${siteInfo.name}, a ${siteInfo.description}.

I've been reading your site and think your audience would find value in an article about [relevant topic]. Based on ${siteInfo.uniqueValue}, I could share:

- [Specific angle 1]
- [Specific angle 2]
- [Specific angle 3]

I'd write the piece exclusively for your site with original research and data.

Would you be interested in discussing this further?

Best,
${siteInfo.name} Team`;
  }

  private generateGenericPitch(opp: LinkOpportunity, siteInfo: any): string {
    return `Hi ${opp.contactName || 'there'},

I'm reaching out from ${siteInfo.name}, a ${siteInfo.description}.

We have ${siteInfo.uniqueValue} that your readers might find valuable. I wanted to explore whether there might be an opportunity to collaborate.

Would you be open to a brief conversation about how we might work together?

Best,
${siteInfo.name} Team`;
  }
}

export default SafeLinkAcquisitionAgent;
