/**
 * Blog Controller
 * AI-curated blog with human oversight
 */

const BlogPost = require('../models/BlogPost.model');
const ModerationQueue = require('../models/ModerationQueue.model');
const GovernanceLog = require('../models/GovernanceLog.model');
const { markdownToHtml } = require('../utils/markdown.util');
const logger = require('../utils/logger.util');
const claudeAPI = require('../services/ClaudeAPI.service');
const BoundaryEnforcer = require('../services/BoundaryEnforcer.service');
const BlogCuration = require('../services/BlogCuration.service');

/**
 * List published blog posts (public)
 * GET /api/blog
 */
async function listPublishedPosts(req, res) {
  try {
    const { limit = 10, skip = 0 } = req.query;

    const posts = await BlogPost.findPublished({
      limit: parseInt(limit),
      skip: parseInt(skip)
    });

    const total = await BlogPost.countByStatus('published');

    res.json({
      success: true,
      posts,
      pagination: {
        total,
        limit: parseInt(limit),
        skip: parseInt(skip),
        hasMore: parseInt(skip) + posts.length < total
      }
    });

  } catch (error) {
    logger.error('List published posts error:', error);
    res.status(500).json({
      error: 'Internal Server Error',
      message: 'An error occurred'
    });
  }
}

/**
 * Get single blog post by slug (public, published only)
 * GET /api/blog/:slug
 */
async function getPublishedPost(req, res) {
  try {
    const { slug } = req.params;

    const post = await BlogPost.findBySlug(slug);

    if (!post || post.status !== 'published') {
      return res.status(404).json({
        error: 'Not Found',
        message: 'Blog post not found'
      });
    }

    // Increment view count
    await BlogPost.incrementViews(post._id);

    res.json({
      success: true,
      post
    });

  } catch (error) {
    logger.error('Get published post error:', error);
    res.status(500).json({
      error: 'Internal Server Error',
      message: 'An error occurred'
    });
  }
}

/**
 * List posts by status (admin only)
 * GET /api/blog/admin/posts?status=draft
 */
async function listPostsByStatus(req, res) {
  try {
    const { status = 'draft', limit = 20, skip = 0 } = req.query;

    const posts = await BlogPost.findByStatus(status, {
      limit: parseInt(limit),
      skip: parseInt(skip)
    });

    const total = await BlogPost.countByStatus(status);

    res.json({
      success: true,
      status,
      posts,
      pagination: {
        total,
        limit: parseInt(limit),
        skip: parseInt(skip)
      }
    });

  } catch (error) {
    logger.error('List posts by status error:', error);
    res.status(500).json({
      error: 'Internal Server Error',
      message: 'An error occurred'
    });
  }
}

/**
 * Get any post by ID (admin only)
 * GET /api/blog/admin/:id
 */
async function getPostById(req, res) {
  try {
    const { id } = req.params;

    const post = await BlogPost.findById(id);

    if (!post) {
      return res.status(404).json({
        error: 'Not Found',
        message: 'Blog post not found'
      });
    }

    res.json({
      success: true,
      post
    });

  } catch (error) {
    logger.error('Get post by ID error:', error);
    res.status(500).json({
      error: 'Internal Server Error',
      message: 'An error occurred'
    });
  }
}

/**
 * Create blog post (admin only)
 * POST /api/blog
 */
async function createPost(req, res) {
  try {
    const { title, slug, content, excerpt, tags, author, tractatus_classification } = req.body;

    // Convert markdown content to HTML if needed
    const content_html = content.includes('# ') ? markdownToHtml(content) : content;

    const post = await BlogPost.create({
      title,
      slug,
      content: content_html,
      excerpt,
      tags,
      author: {
        ...author,
        name: author?.name || req.user.name || req.user.email
      },
      tractatus_classification,
      status: 'draft'
    });

    logger.info(`Blog post created: ${slug} by ${req.user.email}`);

    res.status(201).json({
      success: true,
      post
    });

  } catch (error) {
    logger.error('Create post error:', error);

    // Handle duplicate slug
    if (error.code === 11000) {
      return res.status(409).json({
        error: 'Conflict',
        message: 'A post with this slug already exists'
      });
    }

    res.status(500).json({
      error: 'Internal Server Error',
      message: 'An error occurred'
    });
  }
}

/**
 * Update blog post (admin only)
 * PUT /api/blog/:id
 */
async function updatePost(req, res) {
  try {
    const { id } = req.params;
    const updates = { ...req.body };

    // If content is updated and looks like markdown, convert to HTML
    if (updates.content && updates.content.includes('# ')) {
      updates.content = markdownToHtml(updates.content);
    }

    const success = await BlogPost.update(id, updates);

    if (!success) {
      return res.status(404).json({
        error: 'Not Found',
        message: 'Blog post not found'
      });
    }

    const post = await BlogPost.findById(id);

    logger.info(`Blog post updated: ${id} by ${req.user.email}`);

    res.json({
      success: true,
      post
    });

  } catch (error) {
    logger.error('Update post error:', error);
    res.status(500).json({
      error: 'Internal Server Error',
      message: 'An error occurred'
    });
  }
}

/**
 * Publish blog post (admin only)
 * POST /api/blog/:id/publish
 */
async function publishPost(req, res) {
  try {
    const { id } = req.params;
    const { review_notes } = req.body;

    const post = await BlogPost.findById(id);

    if (!post) {
      return res.status(404).json({
        error: 'Not Found',
        message: 'Blog post not found'
      });
    }

    if (post.status === 'published') {
      return res.status(400).json({
        error: 'Bad Request',
        message: 'Post is already published'
      });
    }

    // Update with review notes if provided
    if (review_notes) {
      await BlogPost.update(id, {
        'moderation.review_notes': review_notes
      });
    }

    // Publish the post
    await BlogPost.publish(id, req.userId);

    const updatedPost = await BlogPost.findById(id);

    logger.info(`Blog post published: ${id} by ${req.user.email}`);

    res.json({
      success: true,
      post: updatedPost,
      message: 'Post published successfully'
    });

  } catch (error) {
    logger.error('Publish post error:', error);
    res.status(500).json({
      error: 'Internal Server Error',
      message: 'An error occurred'
    });
  }
}

/**
 * Delete blog post (admin only)
 * DELETE /api/blog/:id
 */
async function deletePost(req, res) {
  try {
    const { id } = req.params;

    const success = await BlogPost.delete(id);

    if (!success) {
      return res.status(404).json({
        error: 'Not Found',
        message: 'Blog post not found'
      });
    }

    logger.info(`Blog post deleted: ${id} by ${req.user.email}`);

    res.json({
      success: true,
      message: 'Post deleted successfully'
    });

  } catch (error) {
    logger.error('Delete post error:', error);
    res.status(500).json({
      error: 'Internal Server Error',
      message: 'An error occurred'
    });
  }
}

/**
 * Suggest blog topics using AI (admin only)
 * POST /api/blog/suggest-topics
 *
 * TRA-OPS-0002: AI suggests topics, human writes and approves posts
 */
async function suggestTopics(req, res) {
  try {
    const { audience, theme } = req.body;

    // Validate audience
    const validAudiences = ['researcher', 'implementer', 'advocate', 'general'];
    if (!audience || !validAudiences.includes(audience)) {
      return res.status(400).json({
        error: 'Bad Request',
        message: `Audience must be one of: ${validAudiences.join(', ')}`
      });
    }

    logger.info(`Blog topic suggestion requested: audience=${audience}, theme=${theme || 'none'}`);

    // 1. Boundary check (TRA-OPS-0002: Editorial decisions require human oversight)
    const boundaryCheck = BoundaryEnforcer.enforce({
      description: 'Suggest blog topics for editorial calendar',
      text: 'AI provides suggestions, human makes final editorial decisions',
      classification: { quadrant: 'OPERATIONAL' },
      type: 'content_suggestion'
    });

    // Log boundary check
    await GovernanceLog.create({
      action: 'BLOG_TOPIC_SUGGESTION',
      user_id: req.user._id,
      user_email: req.user.email,
      timestamp: new Date(),
      boundary_check: boundaryCheck,
      outcome: boundaryCheck.allowed ? 'QUEUED_FOR_APPROVAL' : 'BLOCKED',
      details: {
        audience,
        theme
      }
    });

    if (!boundaryCheck.allowed) {
      logger.warn(`Blog topic suggestion blocked by BoundaryEnforcer: ${boundaryCheck.section}`);
      return res.status(403).json({
        error: 'Boundary Violation',
        message: boundaryCheck.reasoning,
        section: boundaryCheck.section,
        details: 'This action requires human judgment in values territory'
      });
    }

    // 2. Claude API call for topic suggestions
    const suggestions = await claudeAPI.generateBlogTopics(audience, theme);

    logger.info(`Claude API returned ${suggestions.length} topic suggestions`);

    // 3. Create moderation queue entry (human approval required)
    const queueEntry = await ModerationQueue.create({
      type: 'BLOG_TOPIC_SUGGESTION',
      reference_collection: 'blog_posts',
      data: {
        audience,
        theme,
        suggestions,
        requested_by: req.user.email
      },
      status: 'PENDING_APPROVAL',
      ai_generated: true,
      requires_human_approval: true,
      created_by: req.user._id,
      created_at: new Date(),
      metadata: {
        boundary_check: boundaryCheck,
        governance_policy: 'TRA-OPS-0002'
      }
    });

    logger.info(`Created moderation queue entry: ${queueEntry._id}`);

    // 4. Return response (suggestions queued for human review)
    res.json({
      success: true,
      message: 'Blog topic suggestions generated. Awaiting human review and approval.',
      queue_id: queueEntry._id,
      suggestions,
      governance: {
        policy: 'TRA-OPS-0002',
        boundary_check: boundaryCheck,
        requires_approval: true,
        note: 'Topics are suggestions only. Human must write all blog posts.'
      }
    });

  } catch (error) {
    logger.error('Suggest topics error:', error);

    // Handle Claude API errors specifically
    if (error.message.includes('Claude API')) {
      return res.status(502).json({
        error: 'AI Service Error',
        message: 'Failed to generate topic suggestions. Please try again.',
        details: process.env.NODE_ENV === 'development' ? error.message : undefined
      });
    }

    res.status(500).json({
      error: 'Internal Server Error',
      message: 'An error occurred'
    });
  }
}

/**
 * Draft a full blog post using AI (admin only)
 * POST /api/blog/draft-post
 *
 * TRA-OPS-0002: AI drafts content, human reviews and approves before publication
 * Enforces inst_016, inst_017, inst_018 via BlogCuration service
 */
async function draftBlogPost(req, res) {
  try {
    const { topic, audience, length = 'medium', focus } = req.body;

    // Validate required fields
    if (!topic || !audience) {
      return res.status(400).json({
        error: 'Bad Request',
        message: 'topic and audience are required'
      });
    }

    const validAudiences = ['researcher', 'implementer', 'advocate', 'general'];
    if (!validAudiences.includes(audience)) {
      return res.status(400).json({
        error: 'Bad Request',
        message: `audience must be one of: ${validAudiences.join(', ')}`
      });
    }

    const validLengths = ['short', 'medium', 'long'];
    if (!validLengths.includes(length)) {
      return res.status(400).json({
        error: 'Bad Request',
        message: `length must be one of: ${validLengths.join(', ')}`
      });
    }

    logger.info(`Blog post draft requested: topic="${topic}", audience=${audience}, length=${length}`);

    // Generate draft using BlogCuration service (includes boundary checks and validation)
    const result = await BlogCuration.draftBlogPost({
      topic,
      audience,
      length,
      focus
    });

    const { draft, validation, boundary_check, metadata } = result;

    // Log governance action
    await GovernanceLog.create({
      action: 'BLOG_POST_DRAFT',
      user_id: req.user._id,
      user_email: req.user.email,
      timestamp: new Date(),
      boundary_check,
      outcome: 'QUEUED_FOR_APPROVAL',
      details: {
        topic,
        audience,
        length,
        validation_result: validation.recommendation,
        violations: validation.violations.length,
        warnings: validation.warnings.length
      }
    });

    // Create moderation queue entry (human approval required)
    const queueEntry = await ModerationQueue.create({
      type: 'BLOG_POST_DRAFT',
      reference_collection: 'blog_posts',
      data: {
        topic,
        audience,
        length,
        focus,
        draft,
        validation,
        requested_by: req.user.email
      },
      status: 'PENDING_APPROVAL',
      ai_generated: true,
      requires_human_approval: true,
      created_by: req.user._id,
      created_at: new Date(),
      priority: validation.violations.length > 0 ? 'high' : 'medium',
      metadata: {
        boundary_check,
        governance_policy: 'TRA-OPS-0002',
        tractatus_instructions: ['inst_016', 'inst_017', 'inst_018'],
        model_info: metadata
      }
    });

    logger.info(`Created blog draft queue entry: ${queueEntry._id}, validation: ${validation.recommendation}`);

    // Return response
    res.json({
      success: true,
      message: 'Blog post draft generated. Awaiting human review and approval.',
      queue_id: queueEntry._id,
      draft,
      validation,
      governance: {
        policy: 'TRA-OPS-0002',
        boundary_check,
        requires_approval: true,
        tractatus_enforcement: {
          inst_016: 'No fabricated statistics or unverifiable claims',
          inst_017: 'No absolute assurance terms (guarantee, 100%, etc.)',
          inst_018: 'No unverified production-ready claims'
        }
      }
    });

  } catch (error) {
    logger.error('Draft blog post error:', error);

    // Handle boundary violations
    if (error.message.includes('Boundary violation')) {
      return res.status(403).json({
        error: 'Boundary Violation',
        message: error.message
      });
    }

    // Handle Claude API errors
    if (error.message.includes('Claude API') || error.message.includes('Blog draft generation failed')) {
      return res.status(502).json({
        error: 'AI Service Error',
        message: 'Failed to generate blog draft. Please try again.',
        details: process.env.NODE_ENV === 'development' ? error.message : undefined
      });
    }

    res.status(500).json({
      error: 'Internal Server Error',
      message: 'An error occurred'
    });
  }
}

/**
 * Analyze blog content for Tractatus compliance (admin only)
 * POST /api/blog/analyze-content
 *
 * Validates content against inst_016, inst_017, inst_018
 */
async function analyzeContent(req, res) {
  try {
    const { title, body } = req.body;

    if (!title || !body) {
      return res.status(400).json({
        error: 'Bad Request',
        message: 'title and body are required'
      });
    }

    logger.info(`Content compliance analysis requested: "${title}"`);

    const analysis = await BlogCuration.analyzeContentCompliance({
      title,
      body
    });

    logger.info(`Compliance analysis complete: ${analysis.recommendation}, score: ${analysis.overall_score}`);

    res.json({
      success: true,
      analysis,
      tractatus_enforcement: {
        inst_016: 'No fabricated statistics',
        inst_017: 'No absolute guarantees',
        inst_018: 'No unverified production claims'
      }
    });

  } catch (error) {
    logger.error('Analyze content error:', error);

    if (error.message.includes('Claude API') || error.message.includes('Compliance analysis failed')) {
      return res.status(502).json({
        error: 'AI Service Error',
        message: 'Failed to analyze content. Please try again.',
        details: process.env.NODE_ENV === 'development' ? error.message : undefined
      });
    }

    res.status(500).json({
      error: 'Internal Server Error',
      message: 'An error occurred'
    });
  }
}

/**
 * Get editorial guidelines (admin only)
 * GET /api/blog/editorial-guidelines
 */
async function getEditorialGuidelines(req, res) {
  try {
    const guidelines = BlogCuration.getEditorialGuidelines();

    res.json({
      success: true,
      guidelines
    });

  } catch (error) {
    logger.error('Get editorial guidelines error:', error);
    res.status(500).json({
      error: 'Internal Server Error',
      message: 'An error occurred'
    });
  }
}

module.exports = {
  listPublishedPosts,
  getPublishedPost,
  listPostsByStatus,
  getPostById,
  createPost,
  updatePost,
  publishPost,
  deletePost,
  suggestTopics,
  draftBlogPost,
  analyzeContent,
  getEditorialGuidelines
};
