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

import calendar
from datetime import datetime, timedelta

from odoo import models, fields, api, _

from odoo.exceptions import UserError

from logging import getLogger
_logger = getLogger(__name__)

ls_estatus_declaracion = [('Borrador', 'Borrador'),
                          ('Validado', 'Validado'),
                          ('Verificado', 'Verificado'),
                          ('Cancelado', 'Cancelado')]

ls_estatus_liquidacion = [('Calculado', 'Calculado'),
                          ('Confirmado', 'Confirmado'),
                          ('Cancelado', 'Cancelado')]

ls_estatus_ingresos = [('Registrado', 'Registrado'),
                       ('Validado', 'Validado')]

ls_estatus_pagos = [('Registrado', 'Registrado'),
                    ('por_conciliar', 'Por Conciliar'),
                    ('conciliado', 'Conciliado'),
                    ('Cancelado', 'Devuelto')]


class SgtDeclaraciones(models.Model):
    _name = 'sgt_declaraciones'
    _rec_name = 'numero_declaracion'
    _sql_constraints = [('registros_unique', 'UNIQUE(periodo_id, cuenta_id, partner_id)', 'Ya posee una Declaración Correspondiente al RUC y el Trimestre!')]

    numero_declaracion = fields.Char(string='N° de Declaración', Help="identificador de la Declaración", readonly=True)
    partner_id = fields.Many2one('res.partner', string='Aportante', required=True)
    fecha_actual = fields.Date('Fecha', default=datetime.today(), required=True, readonly=True)
    periodo_id = fields.Many2one('sgt_movimientos_periodos', string='Periodo')
    total_ingreso = fields.Float(string='Total de Ingresos', readonly=True, compute="sum_ingreso", digits=(12, 2))
    estatus = fields.Selection(ls_estatus_declaracion, string='Estatus', default='Borrador')
    cuenta_id = fields.Many2one('sgt_cuentas', string='Cuenta', required=True)
    ingresos_mensuales_ids = fields.One2many('sgt_ingresos_mensuales', 'declaracion_id', string='Ingresos Mensuales')
    generado = fields.Boolean(string='Generado', default=False)
    liquidaciones_ids = fields.One2many('sgt_liquidacion', 'declaracion_id', string='Liquidaciones')
    contribucion_id = fields.Many2one('sgt_contribucion', string='Contribución', default=lambda self: self.env['sgt_contribucion'].search([], order='fecha desc')[0].id, Help="Contribución para cancelar")
    unidad_tributaria_id = fields.Many2one('sgt_unidad_tributaria', string='Unidad Tributaria', default=lambda self: self.env['sgt_unidad_tributaria'].search([], order='fecha desc')[0].id, Help="Unidad Tributaria para cancelar")
    total_contribucion = fields.Float(string='Total de Contribución', compute="sum_contribucion", store=True, digits=(12, 2))

    @api.multi
    @api.depends('ingresos_mensuales_ids')
    def sum_contribucion(self):
        for i in self:
            i.total_contribucion = i.contribucion_id.monto * i.total_ingreso / 100

    @api.multi
    @api.depends('ingresos_mensuales_ids')
    def sum_ingreso(self):
        for i in self:
            for line in i.ingresos_mensuales_ids:
                i.total_ingreso += line.monto

    @api.multi
    def get_ingresos(self, mes, anio):
        self.ingresos_mensuales_ids = [(0, 0, {'declaracion_id': self.id,
                                               'anio': anio,
                                               'mes': mes,
                                               'monto': None,
                                               'comprobante': None,
                                               'verificacion_contribuyente': False,
                                               'verificacion_analista': False})]

    @api.multi
    def declarar_ingresos(self):
        date1 = datetime.strptime(self.periodo_id.desde, "%Y-%m-%d")
        date2 = datetime.strptime(self.periodo_id.hasta, "%Y-%m-%d")
        months_str = calendar.month_name
        while date1 < date2:
            month = date1.month
            year = date1.year
            month_str = months_str[month].title()
            self.get_ingresos(month_str, str(year))
            next_month = month + 1 if month != 12 else 1
            next_year = year + 1 if next_month == 1 else year
            date1 = date1.replace(month=next_month, year=next_year)
        self.generado = True

    @api.multi
    def declaracion_validada(self):
        if self.estatus == 'Borrador':
            for i in self.ingresos_mensuales_ids:
                if i.monto > 0 and i.comprobante:
                    i.verificacion_contribuyente = True
                else:
                    raise UserError(_('Los montos se encuentran en 0,00 o falta comprobante.'))
            self.env['sgt_liquidacion'].create({'total_ingreso': self.total_ingreso,
                                                'declaracion_id': self.id})
            self.env['sgt_movimientos'].create({'partner_id': self.partner_id.id,
                                                'cuenta_id': self.cuenta_id.id,
                                                'estatus': 'cargo',
                                                'concepto_movimiento_id': 1,
                                                'periodo_id': self.periodo_id.id,
                                                'monto_movimiento': self.total_contribucion,
                                                'tipo_movimiento': 'debito',
                                                'declaracion_id': self.id})
            if self.fecha_actual > self.periodo_id.tope:
                date1 = datetime.strptime(self.periodo_id.tope, "%Y-%m-%d")
                date2 = datetime.strptime(self.fecha_actual, "%Y-%m-%d")
                diferencia_dias = date2 - date1
                if diferencia_dias > timedelta(days=365):
                    self.env['sgt_movimientos'].create({'partner_id': self.partner_id.id,
                                                        'cuenta_id': self.cuenta_id.id,
                                                        'estatus': 'cargo',
                                                        'concepto_movimiento_id': 3,
                                                        'periodo_id': self.periodo_id.id,
                                                        'monto_movimiento': 150 * self.unidad_tributaria_id.monto,
                                                        'tipo_movimiento': 'debito',
                                                        'declaracion_id': self.id})
                else:
                    self.env['sgt_movimientos'].create({'partner_id': self.partner_id.id,
                                                        'cuenta_id': self.cuenta_id.id,
                                                        'estatus': 'cargo',
                                                        'concepto_movimiento_id': 3,
                                                        'periodo_id': self.periodo_id.id,
                                                        'monto_movimiento': 100 * self.unidad_tributaria_id.monto,
                                                        'tipo_movimiento': 'debito',
                                                        'declararlaracion_id': self.id})
            self.estatus = 'Validado'

    @api.multi
    def declaracion_verificada(self):
        if self.estatus == 'Validado':
            for i in self.ingresos_mensuales_ids:
                i.verificacion_analista = True
            self.estatus = 'Verificado'
        else:
            return False

    @api.model
    def create(self, values):
        periodo = self.env['sgt_movimientos_periodos'].browse(values['periodo_id'])
        values.update({'numero_declaracion': self.env['ir.sequence'].next_by_code('sgt_declaraciones') + periodo.periodo + '(' + str(periodo.annio) + ')'})
        return super(SgtDeclaraciones, self).create(values)

    @api.onchange('partner_id')
    def _onchange_limpiar_partner_id(self):
        self.cuenta_id = ''


class SgtLiquidacion(models.Model):
    _name = 'sgt_liquidacion'
    _rec_name = 'declaracion_id'

    declaracion_id = fields.Many2one('sgt_declaraciones', 'Declaración')
    total_ingreso = fields.Float('Total de Ingreso', related="declaracion_id.total_ingreso", digits=(12, 2))
    contribucion_id = fields.Many2one('sgt_contribucion', 'Contribución', default=lambda self: self.env['sgt_contribucion'].search([], order='fecha desc')[0].id, Help="Contribución para cancelar")
    total_contribucion = fields.Float('Total de Contribución', compute="sum_contribucion", store=True, digits=(12, 2))

    @api.multi
    @api.depends('total_ingreso')
    def sum_contribucion(self):
        for i in self:
            i.total_contribucion = i.contribucion_id.monto * i.total_ingreso / 100


class SgtContribucion(models.Model):
    _name = 'sgt_contribucion'
    _rec_name = 'monto'

    monto = fields.Float('Porcentaje de Contribución', digits=(12, 2))
    fecha = fields.Date('Fecha')


class SgtUnidadTributaria(models.Model):
    _name = 'sgt_unidad_tributaria'
    _rec_name = 'monto'

    monto = fields.Float('Monto', digits=(12, 2))
    fecha = fields.Date('Fecha')
    gaceta_oficial = fields.Char('Gaceta Oficial')


class SgtIngresosMensuales(models.Model):
    _name = 'sgt_ingresos_mensuales'
    _rec_name = 'mes'

    declaracion_id = fields.Many2one('sgt_declaraciones', 'Declaración')
    anio = fields.Char(string='Año')
    mes = fields.Char(string='Mes')
    monto = fields.Float('Monto Bs', help="Ingresar monto a declarar del mes", digits=(12, 2))
    comprobante = fields.Binary('Comprobante', help='Adjunte el comprobante que soporte el monto del ingreso bruto del mes')
    verificacion_contribuyente = fields.Boolean('Aportante', help='Verificación del contribuyente')
    verificacion_analista = fields.Boolean('Analista', help='Verificación del analista')


class SgtPagos(models.Model):
    _name = 'sgt_pagos'
    _rec_name = 'numero_pago'

    estatus = fields.Selection(ls_estatus_pagos, 'Estatus', default='Registrado')
    numero_pago = fields.Char('Número de Pago', readonly='True', help='El codigo se genera automaticamente')
    partner_id = fields.Many2one('res.partner', string='Aportante')
    cuenta_id = fields.Many2one('sgt_cuentas', string='Cuenta')
    movimiento_id = fields.Many2one('sgt_movimientos', string='Movimiento')
    descripcion = fields.Char(related='movimiento_id.concepto_movimiento_id.descripcion', string='Concepto', readonly=True)
    monto_movimiento = fields.Float(related='movimiento_id.monto_movimiento', string='Monto Movimiento', readonly=True, digits=(12, 2))
    concepto_movimiento_id = fields.Many2one('sgt_conceptos', string='Concepto', compute="tipo_concepto", store=True)
    ingresos_pagos_ids = fields.One2many('sgt_ingresos_pagos', 'pagos_id', string='Registros de Pagos')
    total_pago = fields.Float('Total de Pago', readonly=True, compute="sum_ingreso", digits=(12, 2))
    fecha_actual = fields.Date('Fecha', default=datetime.today(), required=True, readonly=True)
    tasa_bcv_id = fields.Many2one('sgt_tasa_bcv', string='Tasa BCV', default=lambda self: self.env['sgt_tasa_bcv'].search([], order='fecha desc')[0].id)

    @api.multi
    @api.depends('movimiento_id')
    def tipo_concepto(self):
        if self.movimiento_id.concepto_movimiento_id.codigo == '100':
            self.concepto_movimiento_id = 5
        elif self.movimiento_id.concepto_movimiento_id.codigo == '300':
            self.concepto_movimiento_id = 6
        elif self.movimiento_id.concepto_movimiento_id.codigo == '310':
            self.concepto_movimiento_id = 7
        elif self.movimiento_id.concepto_movimiento_id.codigo == '200':
            self.concepto_movimiento_id = 8
        else:
            self.concepto_movimiento_id = ''

    @api.multi
    @api.depends('ingresos_pagos_ids')
    def sum_ingreso(self):
        for i in self:
            for line in i.ingresos_pagos_ids:
                i.total_pago += line.monto

    @api.multi
    def pago_validado(self):
        if self.ingresos_pagos_ids:
            if self.monto_movimiento == self.total_pago and self.movimiento_id.pagado is not True:
                for i in self.ingresos_pagos_ids:
                    if not i.comprobante:
                        raise UserError(_('El Campo de los Adjuntos esta Vacío'))
                    else:
                        i.validado_contribuyente = True
                if self.movimiento_id.concepto_movimiento_id.codigo == '100':
                    self.env['sgt_movimientos'].create({'partner_id': self.partner_id.id,
                                                        'cuenta_id': self.cuenta_id.id,
                                                        'estatus': 'borrador',
                                                        'concepto_movimiento_id': self.concepto_movimiento_id.id,
                                                        'periodo_id': self.movimiento_id.declaracion_id.periodo_id.id,
                                                        'monto_movimiento': self.total_pago,
                                                        'declaracion_id': self.movimiento_id.declaracion_id.id,
                                                        'tipo_movimiento': 'credito'})
                    self.estatus = 'por_conciliar'
                    if self.movimiento_id.concepto_movimiento_id.codigo == '100' and self.fecha_actual > self.movimiento_id.periodo_id.tope:
                        date1 = datetime.strptime(self.movimiento_id.periodo_id.tope, "%Y-%m-%d")
                        date2 = datetime.strptime(self.fecha_actual, "%Y-%m-%d")
                        diferencia_dias = date2 - date1
                        interes_mora = ((self.movimiento_id.monto_movimiento * (1.2 * self.tasa_bcv_id.monto)) * diferencia_dias.days) / 365
                        self.env['sgt_movimientos'].create({'partner_id': self.partner_id.id,
                                                            'cuenta_id': self.cuenta_id.id,
                                                            'estatus': 'cargo',
                                                            'concepto_movimiento_id': 2,
                                                            'periodo_id': self.movimiento_id.declaracion_id.periodo_id.id,
                                                            'monto_movimiento': interes_mora,
                                                            'declaracion_id': self.movimiento_id.declaracion_id.id,
                                                            'tipo_movimiento': 'debito'})
                        if diferencia_dias < timedelta(days=365):
                            interes = (self.movimiento_id.monto_movimiento * 0.28) * diferencia_dias.days
                            if interes >= self.movimiento_id.monto_movimiento:
                                self.env['sgt_movimientos'].create({'partner_id': self.partner_id.id,
                                                                    'cuenta_id': self.cuenta_id.id,
                                                                    'estatus': 'cargo',
                                                                    'concepto_movimiento_id': 4,
                                                                    'periodo_id': self.movimiento_id.declaracion_id.periodo_id.id,
                                                                    'monto_movimiento': self.movimiento_id.monto_movimiento,
                                                                    'declaracion_id': self.movimiento_id.declaracion_id.id,
                                                                    'tipo_movimiento': 'debito'})
                            else:
                                self.env['sgt_movimientos'].create({'partner_id': self.partner_id.id,
                                                                    'cuenta_id': self.cuenta_id.id,
                                                                    'estatus': 'cargo',
                                                                    'concepto_movimiento_id': 4,
                                                                    'periodo_id': self.movimiento_id.declaracion_id.periodo_id.id,
                                                                    'monto_movimiento': interes,
                                                                    'declaracion_id': self.movimiento_id.declaracion_id.id,
                                                                    'tipo_movimiento': 'debito'})
                        elif diferencia_dias > timedelta(days=365) and diferencia_dias < timedelta(days=730):
                            interes = ((self.movimiento_id.monto_movimiento * 150) / 100)
                            self.env['sgt_movimientos'].create({'partner_id': self.partner_id.id,
                                                                'cuenta_id': self.cuenta_id.id,
                                                                'estatus': 'cargo',
                                                                'concepto_movimiento_id': 4,
                                                                'periodo_id': self.movimiento_id.declaracion_id.periodo_id.id,
                                                                'monto_movimiento': interes,
                                                                'declaracion_id': self.movimiento_id.declaracion_id.id,
                                                                'tipo_movimiento': 'debito'})
                        else:
                            interes = ((self.movimiento_id.monto_movimiento * 300) / 100)
                            self.env['sgt_movimientos'].create({'partner_id': self.partner_id.id,
                                                                'cuenta_id': self.cuenta_id.id,
                                                                'estatus': 'cargo',
                                                                'concepto_movimiento_id': 4,
                                                                'periodo_id': self.movimiento_id.declaracion_id.periodo_id.id,
                                                                'monto_movimiento': interes,
                                                                'declaracion_id': self.movimiento_id.declaracion_id.id,
                                                                'tipo_movimiento': 'debito'})
                elif self.movimiento_id.concepto_movimiento_id.codigo == '300':
                    self.env['sgt_movimientos'].create({'partner_id': self.partner_id.id,
                                                        'cuenta_id': self.cuenta_id.id,
                                                        'estatus': 'borrador',
                                                        'concepto_movimiento_id': self.concepto_movimiento_id.id,
                                                        'periodo_id': self.movimiento_id.periodo_id.id,
                                                        'monto_movimiento': self.total_pago,
                                                        'movimiento_id': self.movimiento_id.id,
                                                        'tipo_movimiento': 'credito'})
                    self.estatus = 'por_conciliar'
                elif self.movimiento_id.concepto_movimiento_id.codigo == '200':
                    self.env['sgt_movimientos'].create({'partner_id': self.partner_id.id,
                                                        'cuenta_id': self.cuenta_id.id,
                                                        'estatus': 'borrador',
                                                        'concepto_movimiento_id': self.concepto_movimiento_id.id,
                                                        'periodo_id': self.movimiento_id.periodo_id.id,
                                                        'monto_movimiento': self.total_pago,
                                                        'movimiento_id': self.movimiento_id.id,
                                                        'tipo_movimiento': 'credito'})
                    self.estatus = 'por_conciliar'
                elif self.movimiento_id.concepto_movimiento_id.codigo == '310':
                    self.env['sgt_movimientos'].create({'partner_id': self.partner_id.id,
                                                        'cuenta_id': self.cuenta_id.id,
                                                        'estatus': 'borrador',
                                                        'concepto_movimiento_id': self.concepto_movimiento_id.id,
                                                        'periodo_id': self.movimiento_id.periodo_id.id,
                                                        'monto_movimiento': self.total_pago,
                                                        'movimiento_id': self.movimiento_id.id,
                                                        'tipo_movimiento': 'credito'})
                    self.estatus = 'por_conciliar'
            else:
                raise UserError(_('Los Montos de los Pagos no son Igual al Monto del Movimiento o el movimiento ya fue pagado.'))
        else:
            raise UserError(_('El Campo de Registros de los Pagos se encuentra Vacío.'))

    @api.model
    def create(self, values):
        values.update({'numero_pago': self.env['ir.sequence'].next_by_code('sgt_pagos')})
        return super(SgtPagos, self).create(values)

    @api.onchange('partner_id')
    def _onchange_partner_id(self):
        self.cuenta_id = ''
        self.movimiento_id = ''

    @api.onchange('cuenta_id')
    def _onchange_cuenta_id(self):
        self.movimiento_id = ''


class SgtBancos(models.Model):
    _name = 'sgt_bancos'
    _rec_name = 'nombre'

    codigo = fields.Char('Código')
    nombre = fields.Char('Nombre')


class SgtIngresosPagos(models.Model):
    _name = 'sgt_ingresos_pagos'

    banco_id = fields.Many2one('sgt_bancos', string='Entidad Bancaria')
    referencia = fields.Char(string='Referencia')
    comprobante = fields.Binary(string='Comprobante')
    monto = fields.Float(string='Monto', digits=(12, 2))
    pagos_id = fields.Many2one('sgt_pagos', string='Pago')
    validado_contribuyente = fields.Boolean(string='Validado')

    @api.multi
    @api.depends('pagos_id')
    def name_get(self):
        result = []
        for registro in self:
            name = str(registro.pagos_id.numero_pago)
            result.append((registro.id, name))
        return result


class SgtTasaBCV(models.Model):
    _name = 'sgt_tasa_bcv'
    _rec_name = 'monto'

    monto = fields.Float(string='Tasa', digits=(12, 2))
    fecha = fields.Date(string='Fecha')
