# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)

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

_logger = logging.getLogger(__name__)


class FusionInterCompanyTransfer(models.Model):
    _name = 'fusion.inter.company.transfer'
    _description = 'Inter-Company Inventory Transfer'
    _inherit = ['mail.thread', 'mail.activity.mixin']
    _order = 'create_date desc'
    _rec_name = 'display_name'

    display_name = fields.Char(compute='_compute_display_name')
    config_id = fields.Many2one(
        'fusion.sync.config', string='Remote Instance',
        required=True, ondelete='restrict',
        domain=[('state', '=', 'connected')])
    product_id = fields.Many2one(
        'product.product', string='Product',
        required=True, ondelete='restrict')
    product_mapping_id = fields.Many2one(
        'fusion.product.sync.mapping', string='Product Mapping',
        compute='_compute_product_mapping', store=True)
    quantity = fields.Float(string='Quantity', required=True, default=1.0)
    state = fields.Selection([
        ('draft', 'Draft'),
        ('requested', 'Requested'),
        ('so_created', 'Remote SO Created'),
        ('po_created', 'Local PO Created'),
        ('invoiced', 'Invoiced'),
        ('transferred', 'Transferred'),
        ('done', 'Done'),
        ('error', 'Error'),
        ('cancelled', 'Cancelled'),
    ], string='Status', default='draft', required=True,
        tracking=True, index=True)

    remote_so_id = fields.Integer(string='Remote SO ID', readonly=True)
    remote_so_name = fields.Char(string='Remote SO Reference', readonly=True)
    local_po_id = fields.Many2one(
        'purchase.order', string='Local PO', readonly=True)
    remote_invoice_id = fields.Integer(string='Remote Invoice ID', readonly=True)
    local_bill_id = fields.Many2one(
        'account.move', string='Local Vendor Bill', readonly=True)
    task_id = fields.Many2one(
        'fusion.technician.task', string='Delivery Task', readonly=True)
    warehouse_inventory_id = fields.Many2one(
        'fusion.warehouse.inventory', string='Warehouse Record', readonly=True)
    error_step = fields.Char(string='Failed Step', readonly=True)

    requested_by = fields.Many2one('res.users', string='Requested By',
                                    default=lambda self: self.env.uid)
    notes = fields.Text(string='Notes')

    @api.depends('product_id', 'config_id')
    def _compute_display_name(self):
        for rec in self:
            product = rec.product_id.name or 'No Product'
            remote = rec.config_id.name or 'No Remote'
            rec.display_name = f'{product} <- {remote}'

    @api.depends('product_id', 'config_id')
    def _compute_product_mapping(self):
        Mapping = self.env['fusion.product.sync.mapping']
        for rec in self:
            if rec.product_id and rec.config_id:
                mapping = Mapping.search([
                    ('config_id', '=', rec.config_id.id),
                    ('local_product_id', '=', rec.product_id.product_tmpl_id.id),
                ], limit=1)
                rec.product_mapping_id = mapping.id if mapping else False
            else:
                rec.product_mapping_id = False

    # ── Manual Step-by-Step Actions (preserved) ──

    def action_request(self):
        for rec in self.filtered(lambda r: r.state == 'draft'):
            if not rec.product_mapping_id:
                raise UserError(
                    f'No sync mapping found for {rec.product_id.name} '
                    f'on {rec.config_id.name}. Sync products first.')
            rec.state = 'requested'

    def action_create_remote_so(self):
        for rec in self.filtered(lambda r: r.state == 'requested'):
            try:
                partner_name = (
                    rec.config_id.local_company_name
                    or rec.env.company.name)
                remote_so_id, so_name = rec.config_id._create_remote_sale_order(
                    rec.product_mapping_id, rec.quantity, partner_name)
                rec.write({
                    'remote_so_id': remote_so_id,
                    'remote_so_name': so_name,
                    'state': 'so_created',
                })
                _logger.info('Remote SO %s created for transfer %s',
                             so_name, rec.display_name)
            except Exception as e:
                raise UserError(f'Failed to create remote SO: {e}')

    def action_create_local_po(self):
        for rec in self.filtered(lambda r: r.state == 'so_created'):
            partner = rec.config_id.remote_partner_id
            if not partner:
                partner = self.env['res.partner'].search([
                    ('name', 'ilike', rec.config_id.name),
                ], limit=1)
            if not partner:
                partner = self.env['res.partner'].create({
                    'name': rec.config_id.name,
                    'supplier_rank': 1,
                })

            po = self.env['purchase.order'].create({
                'partner_id': partner.id,
                'order_line': [(0, 0, {
                    'product_id': rec.product_id.id,
                    'product_qty': rec.quantity,
                    'price_unit': rec.product_id.standard_price,
                })],
                'origin': f'ICT from {rec.config_id.name} (SO {rec.remote_so_name or rec.remote_so_id})',
            })
            po.button_confirm()

            rec.write({
                'local_po_id': po.id,
                'state': 'po_created',
            })
            _logger.info('Local PO %s created for transfer %s',
                         po.name, rec.display_name)

    def action_create_invoice(self):
        for rec in self.filtered(lambda r: r.state == 'po_created'):
            try:
                remote_inv_id = rec.config_id._create_remote_invoice(rec.remote_so_id)
                rec.write({
                    'remote_invoice_id': remote_inv_id or 0,
                    'state': 'invoiced',
                })
            except Exception as e:
                _logger.warning('Remote invoice creation failed: %s', e)
                rec.state = 'invoiced'

    def action_create_vendor_bill(self):
        """Create a local vendor bill from the PO (draft, for accounting review)."""
        for rec in self.filtered(lambda r: r.state == 'invoiced' and r.local_po_id):
            if rec.local_bill_id:
                continue
            action = rec.local_po_id.action_create_invoice()
            if action and action.get('res_id'):
                rec.local_bill_id = action['res_id']
            else:
                bills = self.env['account.move'].search([
                    ('purchase_order_count', '>', 0),
                    ('ref', 'ilike', rec.local_po_id.name),
                ], limit=1, order='id desc')
                if bills:
                    rec.local_bill_id = bills.id

    def action_create_delivery_task(self):
        for rec in self.filtered(lambda r: r.state in ('po_created', 'invoiced')):
            try:
                task = self.env['fusion.technician.task'].create({
                    'name': f'Warehouse Transfer: {rec.product_id.name} x{rec.quantity}',
                    'task_type': 'delivery',
                    'description': (
                        f'Transfer {rec.quantity}x {rec.product_id.name} '
                        f'from {rec.config_id.name} shared warehouse.\n'
                        f'Remote SO: {rec.remote_so_name or rec.remote_so_id}\n'
                        f'Local PO: {rec.local_po_id.name if rec.local_po_id else "N/A"}'
                    ),
                })
                rec.task_id = task.id
            except Exception as e:
                _logger.warning('Task creation failed (fusion_tasks may not be configured): %s', e)

    def action_mark_transferred(self):
        for rec in self.filtered(lambda r: r.state == 'invoiced'):
            if rec.warehouse_inventory_id:
                rec.warehouse_inventory_id.action_mark_transferred()
            rec.state = 'transferred'

    def action_complete(self):
        for rec in self.filtered(lambda r: r.state == 'transferred'):
            rec.state = 'done'

    def action_cancel(self):
        for rec in self.filtered(lambda r: r.state not in ('done', 'cancelled')):
            if rec.warehouse_inventory_id:
                rec.warehouse_inventory_id.action_release()
            rec.state = 'cancelled'

    # ── One-Click Automated Transfer ──

    def action_execute_transfer(self):
        """Execute all transfer steps in one click:
        1. Create SO on remote
        2. Create Invoice on remote
        3. Create PO locally
        4. Confirm PO
        5. Create Vendor Bill (draft)
        6. Mark done
        """
        for rec in self:
            if rec.state not in ('draft', 'requested'):
                continue

            if not rec.product_mapping_id:
                rec.write({
                    'state': 'error',
                    'error_step': 'validation',
                    'notes': (rec.notes or '') + '\nNo sync mapping found. Sync products first.',
                })
                continue

            config = rec.config_id
            partner_name = config.local_company_name or rec.env.company.name

            # Step 1: Remote SO
            try:
                remote_so_id, so_name = config._create_remote_sale_order(
                    rec.product_mapping_id, rec.quantity, partner_name)
                rec.write({
                    'remote_so_id': remote_so_id,
                    'remote_so_name': so_name,
                    'state': 'so_created',
                })
                rec.message_post(body=f'Remote SO {so_name} created.')
            except Exception as e:
                rec.write({
                    'state': 'error',
                    'error_step': 'remote_so',
                    'notes': (rec.notes or '') + f'\nFailed at Remote SO: {e}',
                })
                _logger.error('ICT %s: Remote SO failed: %s', rec.id, e)
                continue

            # Step 2: Remote Invoice
            try:
                remote_inv_id = config._create_remote_invoice(remote_so_id)
                rec.write({
                    'remote_invoice_id': remote_inv_id or 0,
                })
                rec.message_post(body=f'Remote Invoice created (ID: {remote_inv_id}).')
            except Exception as e:
                _logger.warning('ICT %s: Remote Invoice failed (non-fatal): %s', rec.id, e)
                rec.message_post(body=f'Remote Invoice skipped: {e}')

            # Step 3: Local PO
            try:
                partner = config.remote_partner_id
                if not partner:
                    partner = self.env['res.partner'].search([
                        ('name', 'ilike', config.name),
                    ], limit=1)
                if not partner:
                    partner = self.env['res.partner'].create({
                        'name': config.name,
                        'supplier_rank': 1,
                    })

                po = self.env['purchase.order'].create({
                    'partner_id': partner.id,
                    'order_line': [(0, 0, {
                        'product_id': rec.product_id.id,
                        'product_qty': rec.quantity,
                        'price_unit': rec.product_id.standard_price,
                    })],
                    'origin': f'ICT from {config.name} (SO {rec.remote_so_name or rec.remote_so_id})',
                })
                po.button_confirm()
                rec.write({
                    'local_po_id': po.id,
                    'state': 'po_created',
                })
                rec.message_post(body=f'Local PO {po.name} created and confirmed.')
            except Exception as e:
                rec.write({
                    'state': 'error',
                    'error_step': 'local_po',
                    'notes': (rec.notes or '') + f'\nFailed at Local PO: {e}',
                })
                _logger.error('ICT %s: Local PO failed: %s', rec.id, e)
                continue

            # Step 4: Local Vendor Bill (draft)
            try:
                action = po.action_create_invoice()
                if action and action.get('res_id'):
                    rec.local_bill_id = action['res_id']
                    rec.message_post(body='Local Vendor Bill created (draft).')
            except Exception as e:
                _logger.warning('ICT %s: Vendor bill creation failed (non-fatal): %s', rec.id, e)

            # Step 5: Done
            rec.write({
                'state': 'done',
            })
            rec.message_post(body='Transfer completed automatically.')
            _logger.info('ICT %s: One-click transfer completed', rec.id)

    def action_retry(self):
        """Reset an errored transfer back to draft for retry."""
        for rec in self.filtered(lambda r: r.state == 'error'):
            rec.write({
                'state': 'draft',
                'error_step': False,
            })
