from odoo import api, fields, models


class RelsumMachine(models.Model):
    """Máquina del cliente (alternador, motor, grupo electrógeno…).

    Una máquina puede tener N OTs históricas — permite trazabilidad cruzada
    por número de serie a lo largo de los años.
    """
    _name = 'relsum.machine'
    _description = 'Máquina del cliente'
    _inherit = ['mail.thread', 'mail.activity.mixin']
    _order = 'marca, tipo, numero_serie'

    name = fields.Char(
        string='Identificación',
        compute='_compute_name',
        store=True,
        index=True,
    )

    # =========================
    # IDENTIFICACIÓN
    # =========================

    marca = fields.Char(string='Marca', tracking=True)
    tipo = fields.Char(string='Tipo / Modelo', tracking=True)
    numero_serie = fields.Char(string='Nº de serie', index=True, tracking=True)

    # =========================
    # CARACTERÍSTICAS ELÉCTRICAS
    # =========================
    # kva / kw / cv son los 3 INTERCAMBIABLES: el usuario puede rellenar
    # cualquiera de los 3 y los otros 2 se recalculan automáticamente.
    # Internamente se gestionan con compute+inverse+store: el "compute"
    # no hace nada (los valores ya están en BD), el "inverse" se dispara
    # cuando el usuario edita ESE campo concreto y recalcula los otros 2.

    voltios = fields.Float(string='Voltios (V)', digits=(10, 2))

    cos_phi = fields.Float(
        string='Factor de potencia (cos φ)',
        digits=(10, 3),
        default=0.85,
        help='Factor de potencia típico en motores industriales: 0.85. '
             'Usado para convertir entre kVA y kW/CV.',
    )

    kva = fields.Float(
        string='Potencia (kVA)',
        digits=(10, 2),
        compute='_compute_power_fields',
        inverse='_inverse_kva',
        store=True,
        readonly=False,
    )
    kw = fields.Float(
        string='Potencia (kW)',
        digits=(10, 2),
        compute='_compute_power_fields',
        inverse='_inverse_kw',
        store=True,
        readonly=False,
    )
    cv = fields.Float(
        string='Potencia (CV)',
        digits=(10, 2),
        compute='_compute_power_fields',
        inverse='_inverse_cv',
        store=True,
        readonly=False,
    )

    rpm = fields.Float(string='RPM', digits=(10, 0))
    amperios = fields.Float(string='Amperios (A)', digits=(10, 2))
    hz = fields.Float(string='Frecuencia (Hz)', digits=(10, 2))

    # =========================
    # PROPIEDAD Y UBICACIÓN
    # =========================

    partner_id = fields.Many2one(
        'res.partner',
        string='Propietario',
        tracking=True,
        index=True,
    )
    planta_id = fields.Many2one(
        'res.partner',
        string='Planta / Ubicación',
        domain="[('parent_id', '=', partner_id)]",
        tracking=True,
        help='Sede del cliente donde está instalada la máquina (contacto hijo del propietario).'
    )

    # =========================
    # HISTORIAL DE OTS
    # =========================

    repair_order_ids = fields.One2many(
        'repair.order',
        'relsum_machine_id',
        string='Histórico de OTs',
    )
    repair_count = fields.Integer(
        string='Nº de OTs',
        compute='_compute_repair_count',
    )

    notes = fields.Text(string='Notas')
    active = fields.Boolean(default=True)

    # =========================
    # COMPUTES
    # =========================

    @api.depends('marca', 'tipo', 'numero_serie')
    def _compute_name(self):
        for rec in self:
            parts = [p for p in (rec.marca, rec.tipo, rec.numero_serie) if p]
            rec.name = ' / '.join(parts) if parts else '(sin identificar)'

    def _compute_power_fields(self):
        # Intencionalmente vacío: kva/kw/cv son store=True y se gestionan
        # por sus 'inverse' respectivos. Odoo exige un compute si hay
        # inverse, pero aquí no hay nada que recalcular al leer.
        pass

    # =========================
    # INVERSE: recalcular los otros 2 campos de potencia
    # =========================

    def _inverse_kva(self):
        for rec in self:
            if rec.cos_phi:
                rec.kw = rec.kva * rec.cos_phi
                rec.cv = rec.kw * 1.35962

    def _inverse_kw(self):
        for rec in self:
            if rec.cos_phi:
                rec.kva = rec.kw / rec.cos_phi
            rec.cv = rec.kw * 1.35962

    def _inverse_cv(self):
        for rec in self:
            kw = rec.cv / 1.35962
            rec.kw = kw
            if rec.cos_phi:
                rec.kva = kw / rec.cos_phi

    # =========================
    # ONCHANGE: aviso al cambiar cos_phi con los 3 campos ya rellenos
    # =========================

    @api.onchange('cos_phi')
    def _onchange_cos_phi_warning(self):
        if self.kva and self.kw and self.cv:
            return {
                'warning': {
                    'title': '¿Recalcular potencia?',
                    'message': (
                        'Esta máquina ya tiene kVA, kW y CV establecidos. '
                        'Si guardas con este nuevo factor de potencia, '
                        'kW y CV se recalcularán automáticamente a partir '
                        'de kVA y el nuevo cos φ, sobrescribiendo los '
                        'valores actuales de kW y CV.'
                    ),
                }
            }

    @api.depends('cos_phi')
    def _compute_recalc_on_cos_phi_change(self):
        # No-op: el recálculo real al GUARDAR (no sólo onchange en UI)
        # se hace en write(), ver más abajo. Este método no se usa como
        # compute de ningún campo; se deja documentado por claridad.
        pass

    def write(self, vals):
        # Si cos_phi cambia y la máquina ya tenía kva/kw/cv rellenos,
        # recalculamos kW y CV a partir de kVA (fuente de verdad) y el
        # nuevo cos φ — igual que advertimos en el onchange de UI.
        # Esto cubre también escrituras por API/import, no sólo el form.
        if 'cos_phi' in vals and 'kva' not in vals and 'kw' not in vals and 'cv' not in vals:
            for rec in self:
                if rec.kva and rec.kw and rec.cv:
                    new_cos_phi = vals['cos_phi']
                    if new_cos_phi:
                        new_kw = rec.kva * new_cos_phi
                        vals_rec = dict(vals)
                        vals_rec['kw'] = new_kw
                        vals_rec['cv'] = new_kw * 1.35962
                        super(RelsumMachine, rec).write(vals_rec)
                        continue
                super(RelsumMachine, rec).write(vals)
            return True
        return super().write(vals)

    @api.depends('repair_order_ids')
    def _compute_repair_count(self):
        for rec in self:
            rec.repair_count = len(rec.repair_order_ids)

    # =========================
    # ACTIONS
    # =========================

    def action_view_repair_orders(self):
        self.ensure_one()
        return {
            'type': 'ir.actions.act_window',
            'name': 'OTs de %s' % self.name,
            'res_model': 'repair.order',
            'view_mode': 'list,form',
            'domain': [('id', 'in', self.repair_order_ids.ids)],
        }
