# -*- 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 StockPicking(models.Model):
    _inherit = 'stock.picking'

    # ── Sale Order link ──

    x_fi_sale_order_id = fields.Many2one(
        'sale.order', string='Sale Order',
        compute='_compute_fi_sale_invoice', store=True)
    x_fi_sale_order_state = fields.Selection(
        related='x_fi_sale_order_id.state', string='SO Status',
        store=True, tracking=False)

    # ── Invoice tracking (customer) ──

    x_fi_invoice_ids = fields.Many2many(
        'account.move', 'stock_picking_invoice_rel',
        'picking_id', 'move_id',
        string='Invoices',
        compute='_compute_fi_sale_invoice', store=True)
    x_fi_invoice_count = fields.Integer(
        compute='_compute_fi_sale_invoice', store=True)
    x_fi_invoice_status = fields.Selection([
        ('no', 'No Invoice'),
        ('invoiced', 'Invoiced'),
        ('paid', 'Paid'),
    ], string='Invoice Status', compute='_compute_fi_sale_invoice', store=True)

    # ── Purchase Order link ──

    x_fi_purchase_order_id = fields.Many2one(
        'purchase.order', string='Purchase Order',
        compute='_compute_fi_purchase_bill', store=True)
    x_fi_purchase_order_state = fields.Selection(
        related='x_fi_purchase_order_id.state', string='PO Status',
        store=True, tracking=False)

    # ── Bill tracking (vendor) ──

    x_fi_bill_ids = fields.Many2many(
        'account.move', 'stock_picking_bill_rel',
        'picking_id', 'move_id',
        string='Vendor Bills',
        compute='_compute_fi_purchase_bill', store=True)
    x_fi_bill_count = fields.Integer(
        compute='_compute_fi_purchase_bill', store=True)
    x_fi_bill_status = fields.Selection([
        ('no', 'No Bill'),
        ('billed', 'Billed'),
        ('paid', 'Paid'),
    ], string='Bill Status', compute='_compute_fi_purchase_bill', store=True)

    @api.depends('sale_id', 'sale_id.invoice_ids', 'sale_id.invoice_ids.payment_state',
                 'origin')
    def _compute_fi_sale_invoice(self):
        for pick in self:
            so = pick.sale_id
            if not so and pick.origin:
                so = self.env['sale.order'].search(
                    [('name', '=', pick.origin)], limit=1)

            pick.x_fi_sale_order_id = so.id if so else False

            if so:
                invoices = so.invoice_ids.filtered(
                    lambda m: m.state == 'posted' and m.move_type == 'out_invoice')
                pick.x_fi_invoice_ids = invoices
                pick.x_fi_invoice_count = len(invoices)

                if not invoices:
                    pick.x_fi_invoice_status = 'no'
                elif all(inv.payment_state in ('paid', 'in_payment', 'reversed')
                         for inv in invoices):
                    pick.x_fi_invoice_status = 'paid'
                else:
                    pick.x_fi_invoice_status = 'invoiced'
            else:
                pick.x_fi_invoice_ids = self.env['account.move']
                pick.x_fi_invoice_count = 0
                pick.x_fi_invoice_status = 'no'

    @api.depends('purchase_id', 'purchase_id.invoice_ids',
                 'purchase_id.invoice_ids.payment_state', 'origin')
    def _compute_fi_purchase_bill(self):
        PO = self.env['purchase.order']
        for pick in self:
            po = pick.purchase_id
            if not po and pick.origin:
                po = PO.search([('name', '=', pick.origin)], limit=1)

            pick.x_fi_purchase_order_id = po.id if po else False

            if po:
                bills = po.invoice_ids.filtered(
                    lambda m: m.state == 'posted' and m.move_type == 'in_invoice')
                pick.x_fi_bill_ids = bills
                pick.x_fi_bill_count = len(bills)

                if not bills:
                    pick.x_fi_bill_status = 'no'
                elif all(b.payment_state in ('paid', 'in_payment', 'reversed')
                         for b in bills):
                    pick.x_fi_bill_status = 'paid'
                else:
                    pick.x_fi_bill_status = 'billed'
            else:
                pick.x_fi_bill_ids = self.env['account.move']
                pick.x_fi_bill_count = 0
                pick.x_fi_bill_status = 'no'

    # ── Smart button actions ──

    def action_view_sale_order(self):
        self.ensure_one()
        if not self.x_fi_sale_order_id:
            return
        return {
            'type': 'ir.actions.act_window',
            'name': 'Sale Order',
            'res_model': 'sale.order',
            'view_mode': 'form',
            'res_id': self.x_fi_sale_order_id.id,
        }

    def action_view_invoices(self):
        self.ensure_one()
        invoices = self.x_fi_invoice_ids
        if not invoices:
            return
        if len(invoices) == 1:
            return {
                'type': 'ir.actions.act_window',
                'name': 'Invoice',
                'res_model': 'account.move',
                'view_mode': 'form',
                'res_id': invoices.id,
            }
        return {
            'type': 'ir.actions.act_window',
            'name': 'Invoices',
            'res_model': 'account.move',
            'view_mode': 'list,form',
            'domain': [('id', 'in', invoices.ids)],
        }

    def action_view_purchase_order(self):
        self.ensure_one()
        if not self.x_fi_purchase_order_id:
            return
        return {
            'type': 'ir.actions.act_window',
            'name': 'Purchase Order',
            'res_model': 'purchase.order',
            'view_mode': 'form',
            'res_id': self.x_fi_purchase_order_id.id,
        }

    def action_view_bills(self):
        self.ensure_one()
        bills = self.x_fi_bill_ids
        if not bills:
            return
        if len(bills) == 1:
            return {
                'type': 'ir.actions.act_window',
                'name': 'Vendor Bill',
                'res_model': 'account.move',
                'view_mode': 'form',
                'res_id': bills.id,
            }
        return {
            'type': 'ir.actions.act_window',
            'name': 'Vendor Bills',
            'res_model': 'account.move',
            'view_mode': 'list,form',
            'domain': [('id', 'in', bills.ids)],
        }

    # ── Booking warning on confirm ──

    def button_validate(self):
        Booking = self.env['fusion.inventory.booking']
        for pick in self.filtered(lambda p: p.picking_type_code == 'outgoing'):
            for move in pick.move_ids:
                active_bookings = Booking.search([
                    ('product_id', '=', move.product_id.id),
                    ('state', '=', 'active'),
                    ('user_id', '!=', self.env.uid),
                ])
                if active_bookings:
                    bookers = ', '.join(active_bookings.mapped('user_id.name'))
                    _logger.warning(
                        'Product %s is booked by %s but being delivered in %s',
                        move.product_id.name, bookers, pick.name)
        return super().button_validate()

    # ── Serial Number Scan ──

    def action_scan_serial_numbers(self):
        self.ensure_one()
        wizard = self.env['fusion.serial.scan.wizard'].create({
            'picking_id': self.id,
        })
        wizard._scan()
        return {
            'type': 'ir.actions.act_window',
            'name': 'Serial Number Scan Results',
            'res_model': 'fusion.serial.scan.wizard',
            'view_mode': 'form',
            'res_id': wizard.id,
            'target': 'new',
        }
