# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo import api, fields, models, tools


class L10nInAccountInvoiceReport(models.Model):
    _name = "l10n_in.account.invoice.report"
    _description = "Account Invoice Statistics"
    _auto = False
    _order = 'date desc'

    account_move_id = fields.Many2one('account.move', string="Account Move")
    company_id = fields.Many2one('res.company', string="Company")
    date = fields.Date(string="Accounting Date")
    name = fields.Char(string="Invoice Number")
    partner_id = fields.Many2one('res.partner', string="Customer")
    is_reverse_charge = fields.Char("Reverse Charge")
    l10n_in_gst_treatment = fields.Selection([
            ('regular', 'Registered Business - Regular'),
            ('composition', 'Registered Business - Composition'),
            ('unregistered', 'Unregistered Business'),
            ('consumer', 'Consumer'),
            ('overseas', 'Overseas'),
            ('special_economic_zone', 'Special Economic Zone'),
            ('deemed_export', 'Deemed Export'),
        ], string="GST Treatment")
    journal_id = fields.Many2one('account.journal', string="Journal")
    state = fields.Selection([('draft', 'Unposted'), ('posted', 'Posted')], string='Status')
    igst_amount = fields.Float(string="IGST Amount")
    cgst_amount = fields.Float(string="CGST Amount")
    sgst_amount = fields.Float(string="SGST Amount")
    cess_amount = fields.Float(string="Cess Amount")
    price_total = fields.Float(string='Total Without Tax')
    total = fields.Float(string="Invoice Total")
    reversed_entry_id = fields.Many2one('account.move', string="Refund Invoice", help="From where this Refund is created")
    shipping_bill_number = fields.Char(string="Shipping Bill Number")
    shipping_bill_date = fields.Date(string="Shipping Bill Date")
    shipping_port_code_id = fields.Many2one('l10n_in.port.code', string='Shipping port code')
    ecommerce_partner_id = fields.Many2one('res.partner', string="E-commerce")
    move_type = fields.Selection(selection=[
        ('entry', 'Journal Entry'),
        ('out_invoice', 'Customer Invoice'),
        ('out_refund', 'Customer Credit Note'),
        ('in_invoice', 'Vendor Bill'),
        ('in_refund', 'Vendor Credit Note'),
        ('out_receipt', 'Sales Receipt'),
        ('in_receipt', 'Purchase Receipt')])
    partner_vat = fields.Char(string="Customer GSTIN")
    ecommerce_vat = fields.Char(string="E-commerce GSTIN")
    tax_rate = fields.Float(string="Rate")
    place_of_supply = fields.Char(string="Place of Supply")
    is_pre_gst = fields.Char(string="Is Pre GST")
    is_ecommerce = fields.Char(string="Is E-commerce")
    b2cl_is_ecommerce = fields.Char(string="B2CL Is E-commerce")
    b2cs_is_ecommerce = fields.Char(string="B2CS Is E-commerce")
    supply_type = fields.Char(string="Supply Type")
    export_type = fields.Char(string="Export Type")  # String from GSTR column.
    refund_export_type = fields.Char(string="UR Type")  # String from GSTR column.
    b2b_type = fields.Char(string="B2B Invoice Type")
    refund_invoice_type = fields.Char(string="Document Type")
    gst_format_date = fields.Char(string="Formated Date")
    gst_format_refund_date = fields.Char(string="Formated Refund Date")
    gst_format_shipping_bill_date = fields.Char(string="Formated Shipping Bill Date")
    tax_id = fields.Many2one('account.tax', string="Tax")

    def _select(self):
        select_str = """
            SELECT min(sub.id) as id,
            sub.move_id,
            sub.account_move_id,
            sub.name,
            sub.state,
            sub.partner_id,
            sub.date,
            sub.l10n_in_gst_treatment,
            sub.ecommerce_partner_id,
            sub.shipping_bill_number,
            sub.shipping_bill_date,
            sub.shipping_port_code_id,
            sub.total * sub.b2cs_refund_sign as total,
            sub.journal_id,
            sub.company_id,
            sub.move_type,
            sub.reversed_entry_id,
            sub.partner_vat,
            sub.ecommerce_vat,
            sub.tax_rate as tax_rate,
            (CASE WHEN count(sub.is_reverse_charge) > 0
                THEN 'Y'
                ELSE 'N'
                END) AS is_reverse_charge,
            sub.place_of_supply,
            sub.is_pre_gst,
            sub.is_ecommerce,
            sub.b2cl_is_ecommerce,
            sub.b2cs_is_ecommerce,
            sub.supply_type,
            sub.export_type,
            sub.refund_export_type,
            sub.b2b_type,
            sub.refund_invoice_type,
            sub.gst_format_date,
            sub.gst_format_refund_date,
            sub.gst_format_shipping_bill_date,
            sum(sub.igst_amount) * sub.amount_sign * sub.b2cs_refund_sign AS igst_amount,
            sum(sub.cgst_amount) * sub.amount_sign * sub.b2cs_refund_sign AS cgst_amount,
            sum(sub.sgst_amount) * sub.amount_sign * sub.b2cs_refund_sign AS sgst_amount,
            avg(sub.cess_amount) * sub.amount_sign * sub.b2cs_refund_sign AS cess_amount,
            sum(sub.price_total) * sub.amount_sign * sub.b2cs_refund_sign AS price_total,
            sub.tax_id
        """
        return select_str

    def _sub_select(self):
        sub_select_str = """
            SELECT aml.id AS id,
                aml.move_id,
                aml.partner_id,
                am.id AS account_move_id,
                am.name,
                am.state,
                am.date,
                am.l10n_in_gst_treatment AS l10n_in_gst_treatment,
                am.l10n_in_reseller_partner_id AS ecommerce_partner_id,
                am.l10n_in_shipping_bill_number AS shipping_bill_number,
                am.l10n_in_shipping_bill_date AS shipping_bill_date,
                am.l10n_in_shipping_port_code_id AS shipping_port_code_id,
                ABS(am.amount_total_signed) AS total,
                am.journal_id,
                aj.company_id,
                am.move_type AS move_type,
                am.reversed_entry_id AS reversed_entry_id,
                am.l10n_in_gstin AS partner_vat,
                CASE WHEN rp.vat IS NULL THEN '' ELSE rp.vat END AS ecommerce_vat,
                (CASE WHEN at.l10n_in_reverse_charge = True
                    THEN True
                    ELSE NULL
                    END)  AS is_reverse_charge,
                (CASE WHEN ps.l10n_in_tin IS NOT NULL
                    THEN concat(ps.l10n_in_tin,'-',ps.name)
                    WHEN ps.id IS NULL and cps.l10n_in_tin IS NOT NULL
                    THEN concat(cps.l10n_in_tin,'-',cps.name)
                    ELSE ''
                    END) AS place_of_supply,
                (CASE WHEN am.move_type in ('out_refund', 'in_refund') and refund_am.date <= to_date('2017-07-01', 'YYYY-MM-DD')
                    THEN 'Y'
                    ELSE 'N'
                    END) as is_pre_gst,

                (CASE WHEN am.l10n_in_reseller_partner_id IS NOT NULL
                    THEN 'Y'
                    ELSE 'N'
                    END) as is_ecommerce,
                (CASE WHEN am.l10n_in_reseller_partner_id IS NOT NULL
                    THEN 'Y'
                    ELSE 'N'
                    END) as b2cl_is_ecommerce,
                (CASE WHEN am.l10n_in_reseller_partner_id IS NOT NULL
                    THEN 'E'
                    ELSE 'OE'
                    END) as b2cs_is_ecommerce,
                (CASE WHEN am.l10n_in_state_id = cp.state_id or p.id IS NULL
                    THEN 'Intra State'
                    WHEN am.l10n_in_state_id != cp.state_id and p.id IS NOT NULL
                    THEN 'Inter State'
                    END) AS supply_type,
                (CASE WHEN am.l10n_in_gst_treatment in ('deemed_export', 'overseas') and am.amount_tax > 0.00
                    THEN 'EXPWP'
                    WHEN am.l10n_in_gst_treatment in ('deemed_export', 'overseas') and am.amount_tax <= 0.00
                    THEN 'EXPWOP'
                    ELSE ''
                    END) AS export_type,
                (CASE WHEN am.l10n_in_gst_treatment in ('deemed_export', 'overseas') and am.amount_tax > 0.00
                    THEN 'EXPWP'
                    WHEN am.l10n_in_gst_treatment in ('deemed_export', 'overseas') and am.amount_tax <= 0.00
                    THEN 'EXPWOP'
                    ELSE 'B2CL'
                    END) AS refund_export_type,
                (CASE WHEN am.l10n_in_gst_treatment = 'regular'
                    THEN 'Regular'
                    WHEN am.l10n_in_gst_treatment = 'deemed_export'
                    THEN 'Deemed'
                    WHEN am.l10n_in_gst_treatment = 'overseas' and am.amount_tax > 0.00
                    THEN 'Export with IGST'
                    WHEN am.l10n_in_gst_treatment = 'special_economic_zone' and am.amount_tax > 0.00
                    THEN 'SEZ with IGST payment'
                    WHEN am.l10n_in_gst_treatment = 'special_economic_zone' and am.amount_tax <= 0.00
                    THEN 'SEZ without IGST payment'
                    END) AS b2b_type,
                (CASE WHEN am.move_type = 'out_refund'
                    THEN 'C'
                    WHEN am.move_type = 'in_refund'
                    THEN 'D'
                    ELSE ''
                    END) as refund_invoice_type,
                (CASE WHEN am.date IS NOT NULL
                    THEN TO_CHAR(am.date, 'DD-MON-YYYY')
                    ELSE ''
                    END) as gst_format_date,
                (CASE WHEN refund_am.date IS NOT NULL
                    THEN TO_CHAR(refund_am.date, 'DD-MON-YYYY')
                    ELSE ''
                    END) as gst_format_refund_date,
                (CASE WHEN am.l10n_in_shipping_bill_date IS NOT NULL
                    THEN TO_CHAR(am.l10n_in_shipping_bill_date, 'DD-MON-YYYY')
                    ELSE ''
                    END) as gst_format_shipping_bill_date,
                CASE WHEN tag_rep_ln.account_tax_report_line_id IN
                    (SELECT res_id FROM ir_model_data WHERE module='l10n_in' AND name in ('tax_report_line_igst', 'tax_report_line_igst_rc'))
                    THEN aml.balance
                    ELSE 0
                    END AS igst_amount,
                CASE WHEN tag_rep_ln.account_tax_report_line_id IN
                    (SELECT res_id FROM ir_model_data WHERE module='l10n_in' AND name in ('tax_report_line_cgst', 'tax_report_line_cgst_rc'))
                    THEN aml.balance
                    ELSE 0
                    END AS cgst_amount,
                CASE WHEN tag_rep_ln.account_tax_report_line_id IN
                    (SELECT res_id FROM ir_model_data WHERE module='l10n_in' AND name in ('tax_report_line_sgst', 'tax_report_line_sgst_rc'))
                    THEN aml.balance
                    ELSE 0
                    END AS sgst_amount,
                (WITH account_tax_temp_table AS (
                    SELECT account_account_tag_id
                    FROM account_tax_report_line_tags_rel
                    WHERE account_tax_report_line_id IN
                        (SELECT res_id FROM ir_model_data where module='l10n_in' AND name in ('tax_report_line_cess', 'tax_report_line_cess_rc'))
                    )
                    SELECT sum(temp_aml.balance) from account_move_line temp_aml
                    JOIN account_account_tag_account_move_line_rel aat_aml_rel_temp ON aat_aml_rel_temp.account_move_line_id = temp_aml.id
                    JOIN account_account_tag aat_temp ON aat_temp.id = aat_aml_rel_temp.account_account_tag_id
                    JOIN account_tax_temp_table tag_rep_ln_temp ON aat_temp.id = tag_rep_ln_temp.account_account_tag_id
                    where temp_aml.move_id = aml.move_id and temp_aml.product_id = aml.product_id
                    ) AS cess_amount,
                CASE WHEN tag_rep_ln.account_tax_report_line_id IN
                    (SELECT res_id FROM ir_model_data WHERE module='l10n_in' AND name in ('tax_report_line_sgst', 'tax_report_line_sgst_rc'))
                    THEN NULL
                    ELSE (CASE WHEN aml.tax_base_amount <> 0 THEN aml.tax_base_amount * (CASE WHEN aml.balance < 0 THEN -1 ELSE 1 END) ELSE NULL END)
                    END AS price_total,
                (CASE WHEN (aj.type = 'sale' AND am.move_type != 'out_refund') or (aj.type = 'purchase' AND at.l10n_in_reverse_charge AND am.move_type != 'in_refund') THEN -1 ELSE 1 END) AS amount_sign,
                (CASE WHEN am.move_type in ('in_refund','out_refund')
                      AND p.vat IS NULL
                      AND am.l10n_in_gst_treatment != 'overseas'
                      AND (ABS(am.amount_total_signed) <= 250000 OR
                          (ps.id = cp.state_id OR p.id IS NULL))
                      THEN -1
                      ELSE 1 END) AS b2cs_refund_sign,
                (CASE WHEN atr.parent_tax IS NOT NULL THEN atr.parent_tax
                    ELSE at.id END) AS tax_id,
                (CASE WHEN atr.parent_tax IS NOT NULL THEN parent_at.amount
                    ELSE at.amount END) AS tax_rate
        """
        return sub_select_str

    def _from(self):
        from_str = """
            FROM account_move_line aml
                JOIN account_move am ON am.id = aml.move_id
                JOIN account_journal aj ON aj.id = am.journal_id
                JOIN res_company c ON c.id = aj.company_id
                LEFT JOIN account_tax at ON at.id = aml.tax_line_id
                JOIN account_account_tag_account_move_line_rel aat_aml_rel ON aat_aml_rel.account_move_line_id = aml.id
                JOIN account_account_tag aat ON aat.id = aat_aml_rel.account_account_tag_id
                JOIN account_tax_report_line_tags_rel tag_rep_ln ON aat.id = tag_rep_ln.account_account_tag_id
                LEFT JOIN res_partner cp ON cp.id = COALESCE(aj.l10n_in_gstin_partner_id, c.partner_id)
                LEFT JOIN res_country_state cps ON cps.id = cp.state_id
                LEFT JOIN account_move refund_am ON refund_am.id = am.reversed_entry_id
                LEFT JOIN res_partner p ON p.id = aml.partner_id
                LEFT JOIN res_country_state ps ON ps.id = am.l10n_in_state_id
                LEFT JOIN res_partner rp ON rp.id = am.l10n_in_reseller_partner_id
                LEFT JOIN account_tax_filiation_rel atr ON atr.child_tax = at.id
                LEFT JOIN account_tax parent_at ON parent_at.id = atr.parent_tax
                """
        return from_str

    def _where(self):
        return """
                WHERE am.state = 'posted'
                    AND tag_rep_ln.account_tax_report_line_id in (SELECT res_id FROM ir_model_data WHERE module='l10n_in' AND name in ('tax_report_line_igst', 'tax_report_line_cgst', 'tax_report_line_sgst', 'tax_report_line_zero_rated', 'tax_report_line_igst_rc', 'tax_report_line_cgst_rc', 'tax_report_line_sgst_rc'))
        """

    def _group_by(self):
        group_by_str = """
        GROUP BY sub.move_id,
            sub.account_move_id,
            sub.name,
            sub.state,
            sub.partner_id,
            sub.date,
            sub.l10n_in_gst_treatment,
            sub.ecommerce_partner_id,
            sub.shipping_bill_number,
            sub.shipping_bill_date,
            sub.shipping_port_code_id,
            sub.total,
            sub.journal_id,
            sub.company_id,
            sub.move_type,
            sub.reversed_entry_id,
            sub.partner_vat,
            sub.ecommerce_vat,
            sub.place_of_supply,
            sub.is_pre_gst,
            sub.is_ecommerce,
            sub.b2cl_is_ecommerce,
            sub.b2cs_is_ecommerce,
            sub.supply_type,
            sub.export_type,
            sub.refund_export_type,
            sub.b2b_type,
            sub.refund_invoice_type,
            sub.gst_format_date,
            sub.gst_format_refund_date,
            sub.gst_format_shipping_bill_date,
            sub.amount_sign,
            sub.tax_id,
            sub.tax_rate,
            sub.b2cs_refund_sign
        """
        return group_by_str

    def init(self):
        tools.drop_view_if_exists(self.env.cr, self._table)
        self.env.cr.execute("""CREATE or REPLACE VIEW %s AS (
            %s
            FROM (
                %s %s %s
            ) AS sub %s)""" % (self._table, self._select(), self._sub_select(),
                self._from(), self._where(), self._group_by()))
