from odoo import api, fields, models, _
from odoo.exceptions import UserError


class GenerateContentWizard(models.TransientModel):
    _name = 'otk.seo.content.generate.wizard'
    _description = 'Generate SEO Content Wizard'

    # === Wizard State ===
    state = fields.Selection([
        ('step_source', 'Content & Source'),
        ('step_settings', 'Settings'),
        ('step_images', 'Images'),
        ('step_review', 'Review & Generate'),
    ], default='step_source', string='Step')

    # === Step 1: Content Type & Source ===
    content_type = fields.Selection([
        ('blog_post', 'Blog Post'),
        ('product_desc', 'Product Description'),
        ('category_desc', 'Category Description'),
        ('landing_page', 'Landing Page Content'),
    ], string='Content Type', required=True, default='blog_post',
        help='Select the type of content you want to generate. Each type has optimized formatting and structure.')

    source_type = fields.Selection([
        ('keywords', 'From Keywords/Topic'),
        ('product', 'From Product'),
        ('existing', 'Optimize Existing Content'),
    ], string='Source', default='keywords',
        help='Choose how to provide input for content generation. Keywords/Topic: enter target keywords and a brief; From Product: use product data; Optimize Existing: improve existing text.')

    source_keywords = fields.Char('Target Keywords',
        help='Enter comma-separated keywords you want the content to rank for (e.g., "best coffee maker, home brewing, espresso machine").')
    source_topic = fields.Text('Topic/Brief',
        help='Describe what the content should cover. The more detail you provide, the better the AI can match your expectations.')
    source_product_id = fields.Many2one('product.template', 'Source Product',
        help='Select a product to generate content about. The AI will use the product name, description, and attributes.')
    source_text = fields.Text('Existing Content',
        help='Paste your existing content here. The AI will optimize it for SEO while maintaining the core message.')

    # === Step 2: Settings ===
    template_id = fields.Many2one('otk.seo.template', 'Content Template',
        domain="[('content_type', '=', content_type)]",
        help='Optional: Choose a template to apply predefined prompts, tone, and formatting. Leave empty for default behavior.')

    brand_voice_id = fields.Many2one('otk.seo.brand.voice', 'Brand Voice',
        default=lambda self: self._default_brand_voice(),
        help='Select a brand voice to ensure the AI generates content matching your brand tone, style, and vocabulary.')

    tone = fields.Selection([
        ('professional', 'Professional'),
        ('casual', 'Casual'),
        ('technical', 'Technical'),
        ('persuasive', 'Persuasive'),
        ('conversational', 'Conversational'),
    ], string='Tone', default='professional',
        help='The writing style for your content. Professional for B2B; Casual for lifestyle; Technical for documentation; Persuasive for sales; Conversational for engaging blog posts.')

    target_word_count = fields.Selection([
        ('short', 'Short (300-500 words)'),
        ('medium', 'Medium (500-1000 words)'),
        ('long', 'Long (1000-2000 words)'),
    ], string='Target Length', default='medium',
        help='Approximate word count for the generated content. Longer content generally performs better for SEO but costs more tokens.')

    language_id = fields.Many2one('res.lang', 'Language',
        default=lambda self: self._default_language(),
        help='The language in which the content will be written. Defaults to your Odoo user language.')

    # === References ===
    reference_ids = fields.Many2many('otk.seo.reference',
        'otk_seo_wizard_reference_rel', 'wizard_id', 'reference_id',
        string='References',
        domain="['|', ('content_type', '=', content_type), ('content_type', '=', 'all')]",
        help='Select reference materials to guide the AI. Max 5 references. These provide examples and inspiration for the generated content.')

    # === Step 3: Image Settings ===
    include_images = fields.Boolean('Generate Images', default=True,
        help='Enable to have AI generate images for your content. Images will be created asynchronously.')
    image_count = fields.Integer('Number of Images', default=1,
        help='How many images to generate. The first image is typically used as the cover image.')
    image_style = fields.Selection([
        ('photorealistic', 'Photorealistic'),
        ('illustration', 'Illustration'),
        ('digital_art', 'Digital Art'),
        ('watercolor', 'Watercolor'),
        ('sketch', 'Sketch'),
        ('3d_render', '3D Render'),
    ], string='Image Style', default='photorealistic',
        help='Visual style for generated images.')

    # === Advanced Options (visible in step 3) ===
    include_toc = fields.Boolean('Include Table of Contents',
        help='Add a table of contents at the beginning of the content. Recommended for longer articles.')
    include_faq = fields.Boolean('Include FAQ Section',
        help='Add a FAQ section at the end. Great for SEO as it can appear in featured snippets.')
    custom_instructions = fields.Text('Custom Instructions',
        help='Any additional instructions for the AI (e.g., "Focus on sustainability", "Include pricing comparisons", "Avoid technical jargon").')

    # === Step 4: Target ===
    blog_id = fields.Many2one('blog.blog', 'Target Blog',
        help='Select which blog to publish to. Leave empty to choose later or use the default blog from settings.')

    # === Cost Estimation ===
    estimated_cost = fields.Integer('Estimated Tokens', compute='_compute_estimated_cost')
    cost_breakdown = fields.Text('Cost Breakdown', compute='_compute_estimated_cost')

    def _default_language(self):
        lang_code = self.env.lang or 'en_US'
        lang = self.env['res.lang']._lang_get(lang_code)
        return lang.id if lang else False

    def _default_brand_voice(self):
        """Return the default brand voice if one exists."""
        return self.env['otk.seo.brand.voice'].search([('is_default', '=', True)], limit=1)

    @api.depends('target_word_count', 'include_images', 'image_count')
    def _compute_estimated_cost(self):
        # Fetch dynamic pricing from API (cached 1h in ir.config_parameter)
        pricing = self.env['otk.seo.content'].get_pricing_estimates()
        text_map = pricing.get('text', {'short': 150, 'medium': 300, 'long': 600})
        tokens_per_image = pricing.get('image', 150)

        for record in self:
            text_tokens = text_map.get(record.target_word_count or 'medium', text_map.get('medium', 300))
            image_tokens = (record.image_count or 0) * tokens_per_image if record.include_images else 0
            record.estimated_cost = text_tokens + image_tokens
            lines = [f"Text generation: ~{text_tokens} tokens"]
            if image_tokens:
                lines.append(f"Image generation ({record.image_count} images): ~{image_tokens} tokens")
            lines.append(f"Total estimate: ~{text_tokens + image_tokens} tokens")
            record.cost_breakdown = '\n'.join(lines)

    @api.onchange('template_id')
    def _onchange_template_id(self):
        if self.template_id:
            self.tone = self.template_id.default_tone
            self.target_word_count = self.template_id.default_word_count
            self.include_images = self.template_id.include_images
            self.image_count = self.template_id.default_image_count
            self.image_style = self.template_id.default_image_style
            self.include_toc = self.template_id.include_toc
            self.include_faq = self.template_id.include_faq
            # Inherit references from template
            if self.template_id.reference_ids:
                self.reference_ids = [(6, 0, self.template_id.reference_ids.ids)]

    @api.onchange('source_type')
    def _onchange_source_type(self):
        if self.source_type == 'product':
            self.content_type = 'product_desc'
        elif self.source_type == 'existing':
            self.content_type = 'blog_post'

    @api.onchange('source_product_id')
    def _onchange_source_product_id(self):
        if self.source_product_id:
            self.source_keywords = self.source_product_id.name
            self.source_topic = self._prepare_product_brief()

    def _prepare_product_brief(self):
        """Prepare product information for AI."""
        if not self.source_product_id:
            return ''

        product = self.source_product_id
        brief = f"Product: {product.name}\n"

        if product.description:
            brief += f"Description: {product.description}\n"
        if product.list_price:
            brief += f"Price: {product.list_price}\n"
        if product.categ_id:
            brief += f"Category: {product.categ_id.complete_name}\n"

        return brief

    # === Step Navigation ===
    def _validate_step_source(self):
        """Validate Step 1 inputs by source type."""
        self.ensure_one()
        if self.source_type == 'keywords' and not self.source_keywords and not self.source_topic:
            raise UserError(_("Please provide keywords or a topic description."))
        if self.source_type == 'product' and not self.source_product_id:
            raise UserError(_("Please select a product."))
        if self.source_type == 'existing' and not self.source_text:
            raise UserError(_("Please provide existing content to optimize."))

    def action_next_step(self):
        """Validate current step and advance to next."""
        self.ensure_one()
        steps = ['step_source', 'step_settings', 'step_images', 'step_review']
        current_idx = steps.index(self.state)

        # Validate current step
        if self.state == 'step_source':
            self._validate_step_source()

        if current_idx < len(steps) - 1:
            self.state = steps[current_idx + 1]

        return self._reopen_wizard()

    def action_prev_step(self):
        """Go back one step."""
        self.ensure_one()
        steps = ['step_source', 'step_settings', 'step_images', 'step_review']
        current_idx = steps.index(self.state)

        if current_idx > 0:
            self.state = steps[current_idx - 1]

        return self._reopen_wizard()

    def _reopen_wizard(self):
        """Reopen the wizard at its current step."""
        return {
            'type': 'ir.actions.act_window',
            'res_model': self._name,
            'res_id': self.id,
            'view_mode': 'form',
            'target': 'new',
        }

    def action_generate(self):
        """Create content record and start generation (final step action)."""
        self.ensure_one()

        # Validate inputs
        self._validate_step_source()

        # Create content record
        content_vals = {
            'name': self._generate_initial_name(),
            'content_type': self.content_type,
            'source_keywords': self.source_keywords,
            'source_topic': self.source_topic,
            'source_product_id': self.source_product_id.id if self.source_product_id else False,
            'source_text': self.source_text,
            'template_id': self.template_id.id if self.template_id else False,
            'brand_voice_id': self.brand_voice_id.id if self.brand_voice_id else False,
            'tone': self.tone,
            'target_word_count': self.target_word_count,
            'language_id': self.language_id.id if self.language_id else False,
            'requested_image_count': self.image_count if self.include_images else 0,
            'image_style': self.image_style if self.include_images else False,
            'blog_id': self.blog_id.id if self.blog_id else False,
            'reference_ids': [(6, 0, self.reference_ids.ids)] if self.reference_ids else False,
            'state': 'draft',
        }

        content = self.env['otk.seo.content'].create(content_vals)

        # Start generation
        content.action_generate()

        # Return action to view the content
        return {
            'type': 'ir.actions.act_window',
            'res_model': 'otk.seo.content',
            'res_id': content.id,
            'view_mode': 'form',
            'target': 'current',
        }

    def _generate_initial_name(self):
        """Generate an initial name for the content."""
        if self.source_keywords:
            return self.source_keywords[:100]
        elif self.source_topic:
            return self.source_topic[:100]
        elif self.source_product_id:
            return f"Content for {self.source_product_id.name}"
        else:
            return _("New SEO Content")
