# -*- coding: utf-8 -*-
"""STEP 12 tests — file archive + retention lifecycle + calendar layers.

    odoo -d <db> -u activeblue_familylaw --test-enable \
         --test-tags familylaw_step12 --stop-after-init

Proves:
  * SHA-256 checksum computed from the attachment bytes;
  * retention class drives the destruction-eligibility date;
  * eligibility detection + cron flagging;
  * destroy logs that destruction happened, removes content, keeps checksum proof;
  * client-file return only at matter close;
  * deadline calendar layer.
"""

import base64
import hashlib
from datetime import date

from dateutil.relativedelta import relativedelta

from odoo.tests.common import TransactionCase, new_test_user, tagged
from odoo.exceptions import UserError


@tagged("post_install", "-at_install", "familylaw", "familylaw_step12")
class TestStep12Archive(TransactionCase):

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.attorney = new_test_user(
            cls.env, login="fl_atty12", name="Attorney 12",
            email="atty12@example.com",
            groups="base.group_user,activeblue_familylaw_v2.group_familylaw_attorney",
        )
        cls.partner = cls.env["res.partner"].create({"name": "Arch Client"})
        cls.case = cls.env["familylaw.case"].create({
            "name": "Archive Matter", "client_id": cls.partner.id,
            "case_type": "dissolution_children",
        })
        cls.rc = cls.env["familylaw.retention.class"].create({
            "name": "Standard", "code": "STD", "retention_years": 6,
        })
        cls.Arch = cls.env["familylaw.archive"]

    def _attachment(self, content=b"hello world"):
        return self.env["ir.attachment"].create({
            "name": "file.pdf",
            "datas": base64.b64encode(content),
        })

    # --- checksum -----------------------------------------------------------
    def test_01_sha256_checksum(self):
        content = b"some file bytes"
        att = self._attachment(content)
        arch = self.Arch.create({
            "name": "Doc", "case_id": self.case.id, "attachment_id": att.id,
        })
        self.assertEqual(arch.checksum, hashlib.sha256(content).hexdigest())

    # --- eligibility date ---------------------------------------------------
    def test_02_eligible_date_from_retention(self):
        arch = self.Arch.create({
            "name": "Doc", "case_id": self.case.id,
            "retention_class_id": self.rc.id, "date_archived": date(2020, 1, 1),
        })
        self.assertEqual(arch.destruction_eligible_date,
                         date(2020, 1, 1) + relativedelta(years=6))

    def test_03_past_eligible_is_eligible(self):
        arch = self.Arch.create({
            "name": "Old", "case_id": self.case.id,
            "retention_class_id": self.rc.id, "date_archived": date(2000, 1, 1),
        })
        self.assertTrue(arch.is_destruction_eligible)

    def test_04_future_not_eligible(self):
        rc = self.env["familylaw.retention.class"].create({
            "name": "Long", "retention_years": 100})
        arch = self.Arch.create({
            "name": "New", "case_id": self.case.id,
            "retention_class_id": rc.id, "date_archived": date(2020, 1, 1),
        })
        self.assertFalse(arch.is_destruction_eligible)

    def test_05_cron_flags_eligible(self):
        arch = self.Arch.create({
            "name": "Old", "case_id": self.case.id,
            "retention_class_id": self.rc.id, "date_archived": date(2000, 1, 1),
        })
        self.assertEqual(arch.retention_state, "retained")
        self.Arch._cron_flag_eligible()
        self.assertEqual(arch.retention_state, "eligible")

    # --- destruction --------------------------------------------------------
    def test_06_destroy_removes_content_keeps_checksum(self):
        content = b"confidential"
        att = self._attachment(content)
        arch = self.Arch.create({
            "name": "Doc", "case_id": self.case.id, "attachment_id": att.id,
            "retention_class_id": self.rc.id,
        })
        cs = arch.checksum
        self.assertTrue(cs)
        arch.with_user(self.attorney).action_destroy()
        self.assertEqual(arch.retention_state, "destroyed")
        self.assertTrue(arch.destroyed_date)
        self.assertFalse(arch.attachment_id)      # content gone
        self.assertEqual(arch.checksum, cs)        # proof retained

    def test_07_destroy_requires_attorney(self):
        arch = self.Arch.create({
            "name": "Doc", "case_id": self.case.id,
            "retention_class_id": self.rc.id, "date_archived": date(2000, 1, 1),
        })
        para = new_test_user(
            self.env, login="fl_para12", name="Para 12", email="p12@example.com",
            groups="base.group_user,activeblue_familylaw_v2.group_familylaw_user",
        )
        with self.assertRaises(UserError):
            arch.with_user(para).action_destroy()

    def test_08_destroy_is_audited(self):
        arch = self.Arch.create({
            "name": "Doc", "case_id": self.case.id,
            "retention_class_id": self.rc.id, "date_archived": date(2000, 1, 1),
        })
        before = len(arch.message_ids)
        arch.with_user(self.attorney).action_destroy()
        self.assertGreater(len(arch.message_ids), before)

    # --- client-file return -------------------------------------------------
    def test_09_return_blocked_when_open(self):
        with self.assertRaises(UserError):
            self.case.with_user(self.attorney).action_return_client_file()

    def test_10_return_on_closed(self):
        self.case.with_user(self.attorney).action_mark_conflict_cleared()
        self.case.with_user(self.attorney).action_close()
        self.case.with_user(self.attorney).action_return_client_file()
        self.assertTrue(self.case.client_file_returned)
        self.assertTrue(self.case.client_file_returned_date)

    # --- calendar layer -----------------------------------------------------
    def test_11_deadline_layer(self):
        proc = self.case.proceeding_ids[0]
        dl = self.env["familylaw.deadline"].create({
            "proceeding_id": proc.id, "name": "Hearing", "deadline_type": "hearing",
            "trigger_date": date(2025, 1, 1), "days": 1, "layer": "hearing",
        })
        self.assertEqual(dl.layer, "hearing")

    def test_12_archive_listed_on_case(self):
        arch = self.Arch.create({"name": "Doc", "case_id": self.case.id})
        self.assertIn(arch, self.case.archive_ids)
