# -*- coding: utf-8 -*-

from markupsafe import Markup
from odoo import api, fields, models


class StatusChangeReasonWizard(models.TransientModel):
    """Wizard to capture reason when changing to specific statuses."""
    _name = 'fusion.status.change.reason.wizard'
    _description = 'Status Change Reason Wizard'

    sale_order_id = fields.Many2one(
        'sale.order',
        string='Sale Order',
        required=True,
        ondelete='cascade',
    )
    
    new_status = fields.Selection(
        selection=[
            ('rejected', 'Rejected by ADP'),  # New: Initial rejection (within 24 hours)
            ('denied', 'Application Denied'),  # Funding denied (after 2-3 weeks)
            ('withdrawn', 'Application Withdrawn'),
            ('on_hold', 'On Hold'),
            ('cancelled', 'Cancelled'),
            ('needs_correction', 'Application Needs Correction'),
        ],
        string='New Status',
        required=True,
    )
    
    # ==========================================================================
    # REJECTION REASON FIELDS (for 'rejected' status - initial submission rejection)
    # ==========================================================================
    rejection_reason = fields.Selection(
        selection=[
            ('name_correction', 'Name Correction Needed'),
            ('healthcard_correction', 'Health Card Correction Needed'),
            ('duplicate_claim', 'Duplicate Claim Exists'),
            ('xml_format_error', 'XML Format/Validation Error'),
            ('missing_info', 'Missing Required Information'),
            ('other', 'Other'),
        ],
        string='Rejection Reason',
        help='Select the reason ADP rejected the submission',
    )
    
    # ==========================================================================
    # DENIAL REASON FIELDS (for 'denied' status - funding denial after review)
    # ==========================================================================
    denial_reason = fields.Selection(
        selection=[
            ('eligibility', 'Client Eligibility Issues'),
            ('recent_funding', 'Previous Funding Within 5 Years'),
            ('medical_justification', 'Insufficient Medical Justification'),
            ('equipment_not_covered', 'Equipment Not Covered by ADP'),
            ('documentation_incomplete', 'Documentation Incomplete'),
            ('other', 'Other'),
        ],
        string='Denial Reason',
        help='Select the reason ADP denied the funding',
    )
    
    # ==========================================================================
    # WITHDRAWAL INTENT (for 'withdrawn' status)
    # ==========================================================================
    withdrawal_intent = fields.Selection(
        selection=[
            ('cancel', 'Cancel Application'),
            ('resubmit', 'Withdraw for Correction & Resubmission'),
        ],
        string='What would you like to do after withdrawal?',
        default='resubmit',
    )

    reason = fields.Text(
        string='Reason / Additional Details',
        help='Please provide additional details for this status change.',
    )
    
    # For on_hold: track the previous status
    previous_status = fields.Char(
        string='Previous Status',
        readonly=True,
    )
    
    # Computed field to determine if reason is required
    reason_required = fields.Boolean(
        compute='_compute_reason_required',
    )
    
    @api.depends('new_status', 'rejection_reason', 'denial_reason')
    def _compute_reason_required(self):
        """Reason text is required for 'other' selections or non-rejection/denial statuses."""
        for wizard in self:
            if wizard.new_status == 'rejected':
                # Reason required if rejection_reason is 'other'
                wizard.reason_required = wizard.rejection_reason == 'other'
            elif wizard.new_status == 'denied':
                # Reason required if denial_reason is 'other'
                wizard.reason_required = wizard.denial_reason == 'other'
            else:
                # For other statuses (on_hold, cancelled, etc.), reason is always required
                wizard.reason_required = True
    
    @api.model
    def default_get(self, fields_list):
        """Set defaults from context."""
        res = super().default_get(fields_list)
        
        if self.env.context.get('active_model') == 'sale.order':
            order_id = self.env.context.get('active_id')
            if order_id:
                order = self.env['sale.order'].browse(order_id)
                res['sale_order_id'] = order_id
                res['previous_status'] = order.x_fc_adp_application_status
        
        if self.env.context.get('default_new_status'):
            res['new_status'] = self.env.context.get('default_new_status')
        
        return res
    
    def _get_status_label(self, status):
        """Get human-readable label for status."""
        labels = {
            'rejected': 'Rejected by ADP',
            'denied': 'Application Denied',
            'withdrawn': 'Application Withdrawn',
            'on_hold': 'On Hold',
            'cancelled': 'Cancelled',
            'needs_correction': 'Application Needs Correction',
        }
        return labels.get(status, status)
    
    def _get_status_icon(self, status):
        """Get FontAwesome icon for status."""
        icons = {
            'rejected': 'fa-times',
            'denied': 'fa-times-circle',
            'withdrawn': 'fa-undo',
            'on_hold': 'fa-pause-circle',
            'cancelled': 'fa-ban',
            'needs_correction': 'fa-exclamation-triangle',
        }
        return icons.get(status, 'fa-info-circle')
    
    def _get_rejection_reason_label(self, reason):
        """Get human-readable label for rejection reason."""
        labels = {
            'name_correction': 'Name Correction Needed',
            'healthcard_correction': 'Health Card Correction Needed',
            'duplicate_claim': 'Duplicate Claim Exists',
            'xml_format_error': 'XML Format/Validation Error',
            'missing_info': 'Missing Required Information',
            'other': 'Other',
        }
        return labels.get(reason, reason)
    
    def _get_denial_reason_label(self, reason):
        """Get human-readable label for denial reason."""
        labels = {
            'eligibility': 'Client Eligibility Issues',
            'recent_funding': 'Previous Funding Within 5 Years',
            'medical_justification': 'Insufficient Medical Justification',
            'equipment_not_covered': 'Equipment Not Covered by ADP',
            'documentation_incomplete': 'Documentation Incomplete',
            'other': 'Other',
        }
        return labels.get(reason, reason)
    
    def action_confirm(self):
        """Confirm status change and post reason to chatter."""
        self.ensure_one()
        
        order = self.sale_order_id
        new_status = self.new_status
        reason = self.reason or ''
        
        # Build chatter message
        status_label = self._get_status_label(new_status)
        icon = self._get_status_icon(new_status)
        user_name = self.env.user.name
        change_date = fields.Date.today().strftime('%B %d, %Y')
        
        # Color scheme for different status types
        status_colors = {
            'rejected': ('#e74c3c', '#fff5f5', '#f5c6cb'),    # Red (lighter)
            'denied': ('#dc3545', '#fff5f5', '#f5c6cb'),      # Red
            'withdrawn': ('#6c757d', '#f8f9fa', '#dee2e6'),   # Gray
            'on_hold': ('#fd7e14', '#fff8f0', '#ffecd0'),     # Orange
            'cancelled': ('#dc3545', '#fff5f5', '#f5c6cb'),   # Red
            'needs_correction': ('#ffc107', '#fffbf0', '#ffeeba'),  # Yellow
        }
        header_color, bg_color, border_color = status_colors.get(new_status, ('#17a2b8', '#f0f9ff', '#bee5eb'))
        
        # Build initial update vals
        update_vals = {'x_fc_adp_application_status': new_status}
        if new_status == 'withdrawn':
            update_vals['x_fc_previous_status_before_withdrawal'] = self.previous_status
        
        # =================================================================
        # REJECTED: ADP rejected submission (within 24 hours)
        # =================================================================
        if new_status == 'rejected':
            rejection_reason = self.rejection_reason
            rejection_label = self._get_rejection_reason_label(rejection_reason)
            
            # Store rejection details in sale order
            current_count = order.x_fc_rejection_count or 0
            update_vals.update({
                'x_fc_rejection_reason': rejection_reason,
                'x_fc_rejection_reason_other': reason if rejection_reason == 'other' else False,
                'x_fc_rejection_date': fields.Date.today(),
                'x_fc_rejection_count': current_count + 1,
            })
            
            # Build rejection message
            details_html = ''
            if rejection_reason == 'other' and reason:
                details_html = f'<p><strong>Details:</strong> {reason}</p>'
            
            message_body = f'''
            <div class="alert alert-danger" role="alert">
                <h5 class="alert-heading"><i class="fa {icon}"></i> Submission Rejected by ADP</h5>
                <ul>
                    <li><strong>Rejection #:</strong> {current_count + 1}</li>
                    <li><strong>Reason:</strong> {rejection_label}</li>
                    <li><strong>Date:</strong> {change_date}</li>
                    <li><strong>Recorded By:</strong> {user_name}</li>
                </ul>
                {details_html}
                <hr>
                <p class="mb-0"><i class="fa fa-info-circle"></i> <strong>Next Step:</strong> Correct the issue and resubmit the application.</p>
            </div>
            '''
        
        # =================================================================
        # DENIED: Funding denied by ADP (after 2-3 weeks review)
        # =================================================================
        elif new_status == 'denied':
            denial_reason = self.denial_reason
            denial_label = self._get_denial_reason_label(denial_reason)
            
            # Store denial details in sale order
            update_vals.update({
                'x_fc_denial_reason': denial_reason,
                'x_fc_denial_reason_other': reason if denial_reason == 'other' else False,
                'x_fc_denial_date': fields.Date.today(),
            })
            
            # Build denial message
            details_html = ''
            if denial_reason == 'other' and reason:
                details_html = f'<p><strong>Details:</strong> {reason}</p>'
            
            message_body = f'''
            <div class="alert alert-danger" role="alert">
                <h5 class="alert-heading"><i class="fa {icon}"></i> Funding Denied by ADP</h5>
                <ul>
                    <li><strong>Denial Reason:</strong> {denial_label}</li>
                    <li><strong>Date:</strong> {change_date}</li>
                    <li><strong>Recorded By:</strong> {user_name}</li>
                </ul>
                {details_html}
            </div>
            '''
        
        # =================================================================
        # ON HOLD: Application put on hold
        # Message is posted by _send_on_hold_email() to avoid duplicates
        # =================================================================
        elif new_status == 'on_hold':
            update_vals['x_fc_on_hold_date'] = fields.Date.today()
            update_vals['x_fc_previous_status_before_hold'] = self.previous_status
            # Don't post message here - _send_on_hold_email() will post the message
            message_body = None
        elif new_status == 'withdrawn':
            # Handled entirely below based on withdrawal_intent
            message_body = None
        elif new_status == 'cancelled':
            # Cancelled has its own detailed message posted later
            message_body = None
        else:
            message_body = f'''
            <div class="alert alert-warning" role="alert">
                <h5 class="alert-heading"><i class="fa {icon}"></i> Status Changed: {status_label}</h5>
                <ul>
                    <li><strong>Changed By:</strong> {user_name}</li>
                    <li><strong>Date:</strong> {change_date}</li>
                </ul>
                <hr>
                <p class="mb-0"><strong>Reason:</strong> {reason}</p>
            </div>
            '''
        
        # Post to chatter (except for cancelled which has its own detailed message)
        if message_body:
            order.message_post(
                body=Markup(message_body),
                message_type='notification',
                subtype_xmlid='mail.mt_note',
            )
        
        # Update the status (this will trigger the write() method)
        # Use context to skip the wizard trigger and skip auto-email for needs_correction
        # (we send it below with the reason text)
        write_ctx = {'skip_status_validation': True}
        if new_status == 'needs_correction':
            write_ctx['skip_correction_email'] = True
        order.with_context(**write_ctx).write(update_vals)
        
        # =================================================================
        # NEEDS CORRECTION: Send email with the reason from this wizard
        # =================================================================
        if new_status == 'needs_correction':
            order._send_correction_needed_email(reason=reason)
        
        # =================================================================
        # WITHDRAWN: Branch based on withdrawal intent
        # =================================================================
        if new_status == 'withdrawn':
            intent = self.withdrawal_intent

            if intent == 'cancel':
                # ---------------------------------------------------------
                # WITHDRAW & CANCEL: Cancel invoices + SO
                # ---------------------------------------------------------
                cancelled_invoices = []
                cancelled_so = False

                # Cancel related invoices first
                invoices = order.invoice_ids.filtered(lambda inv: inv.state != 'cancel')
                for invoice in invoices:
                    try:
                        inv_msg = Markup(f'''
                        <div class="alert alert-danger" role="alert">
                            <h5 class="alert-heading"><i class="fa fa-ban"></i> Invoice Cancelled (Withdrawal)</h5>
                            <ul>
                                <li><strong>Related Order:</strong> {order.name}</li>
                                <li><strong>Cancelled By:</strong> {user_name}</li>
                                <li><strong>Date:</strong> {change_date}</li>
                            </ul>
                            <hr>
                            <p class="mb-0"><strong>Reason:</strong> {reason}</p>
                        </div>
                        ''')
                        invoice.message_post(
                            body=inv_msg,
                            message_type='notification',
                            subtype_xmlid='mail.mt_note',
                        )
                        if invoice.state == 'posted':
                            invoice.button_draft()
                        invoice.button_cancel()
                        cancelled_invoices.append(invoice.name)
                    except Exception as e:
                        warn_msg = Markup(f'''
                        <div class="alert alert-warning" role="alert">
                            <p class="mb-0"><i class="fa fa-exclamation-triangle"></i> <strong>Warning:</strong> Could not cancel invoice {invoice.name}</p>
                            <p class="mb-0 small">{str(e)}</p>
                        </div>
                        ''')
                        order.message_post(
                            body=warn_msg,
                            message_type='notification',
                            subtype_xmlid='mail.mt_note',
                        )

                # Cancel the sale order itself
                if order.state not in ('cancel', 'done'):
                    try:
                        order._action_cancel()
                        cancelled_so = True
                    except Exception as e:
                        warn_msg = Markup(f'''
                        <div class="alert alert-warning" role="alert">
                            <p class="mb-0"><i class="fa fa-exclamation-triangle"></i> <strong>Warning:</strong> Could not cancel sale order</p>
                            <p class="mb-0 small">{str(e)}</p>
                        </div>
                        ''')
                        order.message_post(
                            body=warn_msg,
                            message_type='notification',
                            subtype_xmlid='mail.mt_note',
                        )

                # Build cancellation summary
                invoice_list_html = ''
                if cancelled_invoices:
                    invoice_items = ''.join([f'<li>{inv}</li>' for inv in cancelled_invoices])
                    invoice_list_html = f'<li><strong>Invoices Cancelled:</strong><ul>{invoice_items}</ul></li>'

                so_status = 'Cancelled' if cancelled_so else 'Not applicable'
                summary_msg = Markup(f'''
                <div class="alert alert-danger" role="alert">
                    <h5 class="alert-heading"><i class="fa fa-ban"></i> Application Withdrawn &amp; Cancelled</h5>
                    <ul>
                        <li><strong>Withdrawn By:</strong> {user_name}</li>
                        <li><strong>Date:</strong> {change_date}</li>
                        <li><strong>Sale Order:</strong> {so_status}</li>
                        {invoice_list_html}
                    </ul>
                    <hr>
                    <p class="mb-0"><strong>Reason:</strong> {reason}</p>
                </div>
                ''')
                order.message_post(
                    body=summary_msg,
                    message_type='notification',
                    subtype_xmlid='mail.mt_note',
                )
                order._send_withdrawal_email(reason=reason, intent='cancel')

            else:
                # ---------------------------------------------------------
                # WITHDRAW & RESUBMIT: Return to ready_submission
                # ---------------------------------------------------------
                order.with_context(skip_status_validation=True).write({
                    'x_fc_adp_application_status': 'ready_submission',
                    'x_fc_previous_status_before_withdrawal': self.previous_status,
                })

                resubmit_msg = Markup(f'''
                <div class="alert alert-info" role="alert">
                    <h5 class="alert-heading"><i class="fa fa-undo"></i> Application Withdrawn for Correction</h5>
                    <ul>
                        <li><strong>Withdrawn By:</strong> {user_name}</li>
                        <li><strong>Date:</strong> {change_date}</li>
                        <li><strong>Status Returned To:</strong> Ready for Submission</li>
                    </ul>
                    <hr>
                    <p class="mb-0"><strong>Reason:</strong> {reason}</p>
                    <p class="mb-0 mt-2"><i class="fa fa-info-circle"></i> Make corrections and click <strong>Submit Application</strong> to resubmit.</p>
                </div>
                ''')
                order.message_post(
                    body=resubmit_msg,
                    message_type='notification',
                    subtype_xmlid='mail.mt_note',
                )
                order._send_withdrawal_email(reason=reason, intent='resubmit')
        
        # =================================================================
        # ON HOLD: Send email notification to all parties
        # =================================================================
        if new_status == 'on_hold':
            order._send_on_hold_email(reason=reason)
        
        # =================================================================
        # CANCELLED: Also cancel the sale order and all related invoices
        # =================================================================
        if new_status == 'cancelled':
            cancelled_invoices = []
            cancelled_so = False
            user_name = self.env.user.name
            cancel_date = fields.Date.today().strftime('%B %d, %Y')
            
            # Cancel related invoices first
            invoices = order.invoice_ids.filtered(lambda inv: inv.state != 'cancel')
            for invoice in invoices:
                try:
                    # Post cancellation reason to invoice chatter
                    inv_msg = Markup(f'''
                    <div class="alert alert-danger" role="alert">
                        <h5 class="alert-heading"><i class="fa fa-ban"></i> Invoice Cancelled</h5>
                        <ul>
                            <li><strong>Related Order:</strong> {order.name}</li>
                            <li><strong>Cancelled By:</strong> {user_name}</li>
                            <li><strong>Date:</strong> {cancel_date}</li>
                        </ul>
                        <hr>
                        <p class="mb-0"><strong>Reason:</strong> {reason}</p>
                    </div>
                    ''')
                    invoice.message_post(
                        body=inv_msg,
                        message_type='notification',
                        subtype_xmlid='mail.mt_note',
                    )
                    # Cancel the invoice (button_cancel or button_draft then cancel)
                    if invoice.state == 'posted':
                        invoice.button_draft()
                    invoice.button_cancel()
                    cancelled_invoices.append(invoice.name)
                except Exception as e:
                    warn_msg = Markup(f'''
                    <div class="alert alert-warning" role="alert">
                        <p class="mb-0"><i class="fa fa-exclamation-triangle"></i> <strong>Warning:</strong> Could not cancel invoice {invoice.name}</p>
                        <p class="mb-0 small">{str(e)}</p>
                    </div>
                    ''')
                    order.message_post(
                        body=warn_msg,
                        message_type='notification',
                        subtype_xmlid='mail.mt_note',
                    )
            
            # Cancel the sale order itself
            if order.state not in ('cancel', 'done'):
                try:
                    order._action_cancel()
                    cancelled_so = True
                except Exception as e:
                    warn_msg = Markup(f'''
                    <div class="alert alert-warning" role="alert">
                        <p class="mb-0"><i class="fa fa-exclamation-triangle"></i> <strong>Warning:</strong> Could not cancel sale order</p>
                        <p class="mb-0 small">{str(e)}</p>
                    </div>
                    ''')
                    order.message_post(
                        body=warn_msg,
                        message_type='notification',
                        subtype_xmlid='mail.mt_note',
                    )
            
            # Build cancellation summary
            invoice_list_html = ''
            if cancelled_invoices:
                invoice_items = ''.join([f'<li>{inv}</li>' for inv in cancelled_invoices])
                invoice_list_html = f'<li><strong>Invoices Cancelled:</strong><ul>{invoice_items}</ul></li>'
            
            # Post comprehensive summary to chatter
            so_status = 'Cancelled' if cancelled_so else 'Not applicable'
            summary_msg = Markup(f'''
            <div class="alert alert-danger" role="alert">
                <h5 class="alert-heading"><i class="fa fa-ban"></i> Application Cancelled</h5>
                <ul>
                    <li><strong>Cancelled By:</strong> {user_name}</li>
                    <li><strong>Date:</strong> {cancel_date}</li>
                    <li><strong>Sale Order:</strong> {so_status}</li>
                    {invoice_list_html}
                </ul>
                <hr>
                <p class="mb-0"><strong>Reason for Cancellation:</strong> {reason}</p>
            </div>
            ''')
            order.message_post(
                body=summary_msg,
                message_type='notification',
                subtype_xmlid='mail.mt_note',
            )
        
        return {'type': 'ir.actions.act_window_close'}
