module Deontic.Civil.Prescription () where

import Deontic.Core.Types
import Deontic.Core.Verdict
import Deontic.Core.Adjudicate
import Deontic.Core.Layer (Resolvable)
import Deontic.Civil.Types

-- ═══════════════════════════════════════════════
-- 소멸시효 — Prescription (§162, §168, §174)
--
-- §157: 기간을 연으로 정한 때에는 역에 의하여 계산한다.
-- addGregorianYearsClip handles leap years correctly.
-- ═══════════════════════════════════════════════

type instance Resolvable PrescriptionAct = '[Interruption, Expiration]

-- 제162조 ① (채권의 소멸시효)
-- "채권은 10년간 행사하지 아니하면 소멸시효가 완성한다."
--
-- Expiration layer (base): calendar-year comparison
instance Adjudicate PrescriptionAct '[Expiration] where
  adjudicate :: PrescriptionAct -> Facts PrescriptionAct -> Judgment '[Expiration]
adjudicate PrescriptionAct
_ Facts PrescriptionAct
facts
    | Integer -> Day -> Day
addGregorianYearsClip (Int -> Integer
forall a. Integral a => a -> Integer
toInteger (PrescriptionFacts -> Int
pfPeriodYears Facts PrescriptionAct
PrescriptionFacts
facts)) (PrescriptionFacts -> Day
pfClaimDate Facts PrescriptionAct
PrescriptionFacts
facts)
        Day -> Day -> Bool
forall a. Ord a => a -> a -> Bool
<= PrescriptionFacts -> Day
pfCurrentDate Facts PrescriptionAct
PrescriptionFacts
facts =
        Verdict -> ArticleRef -> Text -> Judgment '[Expiration]
forall l. Verdict -> ArticleRef -> Text -> Judgment '[l]
JBase Verdict
Void
          (Text -> Int -> Maybe Int -> ArticleRef
ArticleRef Text
"민법" Int
162 (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
1))
          Text
"채권은 10년간 행사하지 아니하면 소멸시효가 완성한다."
    | Bool
otherwise =
        Verdict -> ArticleRef -> Text -> Judgment '[Expiration]
forall l. Verdict -> ArticleRef -> Text -> Judgment '[l]
JBase Verdict
Valid
          (Text -> Int -> Maybe Int -> ArticleRef
ArticleRef Text
"민법" Int
162 (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
1))
          Text
"소멸시효기간이 경과하지 아니하였다."

-- 제168조 (시효중단의 사유), 제174조 (시효중단의 효력)
-- "시효가 중단된 때에는 중단까지에 경과한 시효기간은 이를 산입하지 아니하고
--  중단사유가 종료한 때로부터 새로이 진행한다."
--
-- Interruption layer (override): if interrupted, recalculate from interruption date
instance Adjudicate PrescriptionAct rest
      => Adjudicate PrescriptionAct (Interruption ': rest) where
  adjudicate :: PrescriptionAct
-> Facts PrescriptionAct -> Judgment (Interruption : rest)
adjudicate PrescriptionAct
act Facts PrescriptionAct
facts
    | Just Day
intDate <- PrescriptionFacts -> Maybe Day
pfInterruptedOn Facts PrescriptionAct
PrescriptionFacts
facts
    , Integer -> Day -> Day
addGregorianYearsClip (Int -> Integer
forall a. Integral a => a -> Integer
toInteger (PrescriptionFacts -> Int
pfPeriodYears Facts PrescriptionAct
PrescriptionFacts
facts)) Day
intDate
        Day -> Day -> Bool
forall a. Ord a => a -> a -> Bool
> PrescriptionFacts -> Day
pfCurrentDate Facts PrescriptionAct
PrescriptionFacts
facts =
        Judgment rest
-> Verdict -> ArticleRef -> Text -> Judgment (Interruption : rest)
forall (prev :: [*]) l.
Judgment prev
-> Verdict -> ArticleRef -> Text -> Judgment (l : prev)
JOverride (forall act (layers :: [*]).
Adjudicate act layers =>
act -> Facts act -> Judgment layers
adjudicate @_ @rest PrescriptionAct
act Facts PrescriptionAct
facts)
                  Verdict
Valid
                  (Text -> Int -> Maybe Int -> ArticleRef
ArticleRef Text
"민법" Int
174 Maybe Int
forall a. Maybe a
Nothing)
                  Text
"시효가 중단된 때에는 중단까지에 경과한 시효기간은 이를 산입하지 아니하고 중단사유가 종료한 때로부터 새로이 진행한다."
    | Bool
otherwise =
        Judgment rest -> Judgment (Interruption : rest)
forall (prev :: [*]) l. Judgment prev -> Judgment (l : prev)
JDelegate (forall act (layers :: [*]).
Adjudicate act layers =>
act -> Facts act -> Judgment layers
adjudicate @_ @rest PrescriptionAct
act Facts PrescriptionAct
facts)