module Deontic.Civil.SaleWarranty () where

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

-- ═══════════════════════════════════════════════
-- 하자담보책임 — Sale Warranty (§580, §581, §582)
--
-- §580①: 매매의 목적물에 하자가 있는 때에는 매수인은
--         계약의 해제 또는 손해배상을 청구할 수 있다.
-- §580②: 그러나 매수인이 하자 있는 것을 알았거나 과실로 인하여
--         이를 알지 못한 때에는 그러하지 아니하다.
-- §581: 중대한 하자 → 계약해제 가능.
-- §582: 매수인이 사실을 안 날로부터 6월 내에 행사.
--
-- BuyerKnowledge layer: §580② 매수인 악의·과실 → Valid (면책)
-- ═══════════════════════════════════════════════

type instance Resolvable WarrantyAct = '[BuyerKnowledge, Base]

-- 제580조 제1항 (매도인의 하자담보책임)
instance Adjudicate WarrantyAct '[Base] where
  adjudicate :: WarrantyAct -> Facts WarrantyAct -> Judgment '[Base]
adjudicate WarrantyAct
_ Facts WarrantyAct
facts
    | Bool -> Bool
not (WarrantyFacts -> Bool
wfDefectExists Facts WarrantyAct
WarrantyFacts
facts) =
        Verdict -> ArticleRef -> Text -> Judgment '[Base]
forall l. Verdict -> ArticleRef -> Text -> Judgment '[l]
JBase Verdict
Valid
          (Text -> Int -> Maybe Int -> ArticleRef
ArticleRef Text
"민법" Int
580 (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
1))
          Text
"매매 목적물에 하자가 없으므로 하자담보책임이 없다."
    | Bool -> Bool
not (WarrantyFacts -> Bool
wfNotifiedInTime Facts WarrantyAct
WarrantyFacts
facts) =
        Verdict -> ArticleRef -> Text -> Judgment '[Base]
forall l. Verdict -> ArticleRef -> Text -> Judgment '[l]
JBase Verdict
Valid
          (Text -> Int -> Maybe Int -> ArticleRef
ArticleRef Text
"민법" Int
582 Maybe Int
forall a. Maybe a
Nothing)
          Text
"매수인이 사실을 안 날로부터 6월 내에 행사하지 아니하여 하자담보책임을 물을 수 없다."
    | WarrantyFacts -> Bool
wfSignificant Facts WarrantyAct
WarrantyFacts
facts =
        Verdict -> ArticleRef -> Text -> Judgment '[Base]
forall l. Verdict -> ArticleRef -> Text -> Judgment '[l]
JBase Verdict
Void
          (Text -> Int -> Maybe Int -> ArticleRef
ArticleRef Text
"민법" Int
580 (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
1))
          Text
"매매 목적물에 중대한 하자가 있어 계약의 해제 및 손해배상을 청구할 수 있다."
    | Bool
otherwise =
        Verdict -> ArticleRef -> Text -> Judgment '[Base]
forall l. Verdict -> ArticleRef -> Text -> Judgment '[l]
JBase Verdict
Voidable
          (Text -> Int -> Maybe Int -> ArticleRef
ArticleRef Text
"민법" Int
580 (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
1))
          Text
"매매 목적물에 하자가 있어 손해배상을 청구할 수 있다."

-- 제580조 제2항 (매수인의 악의·과실)
instance Adjudicate WarrantyAct rest
      => Adjudicate WarrantyAct (BuyerKnowledge ': rest) where
  adjudicate :: WarrantyAct
-> Facts WarrantyAct -> Judgment (BuyerKnowledge : rest)
adjudicate WarrantyAct
act Facts WarrantyAct
facts
    | WarrantyFacts -> Bool
wfBuyerKnew Facts WarrantyAct
WarrantyFacts
facts
    , let prev :: Judgment rest
prev = forall act (layers :: [*]).
Adjudicate act layers =>
act -> Facts act -> Judgment layers
adjudicate @_ @rest WarrantyAct
act Facts WarrantyAct
facts
    , Judgment rest -> Verdict
forall (layers :: [*]). Judgment layers -> Verdict
verdict Judgment rest
prev Verdict -> Verdict -> Bool
forall a. Eq a => a -> a -> Bool
/= Verdict
Valid =
        Judgment rest
-> Verdict
-> ArticleRef
-> Text
-> Judgment (BuyerKnowledge : rest)
forall (prev :: [*]) l.
Judgment prev
-> Verdict -> ArticleRef -> Text -> Judgment (l : prev)
JOverride Judgment rest
prev
                  Verdict
Valid
                  (Text -> Int -> Maybe Int -> ArticleRef
ArticleRef Text
"민법" Int
580 (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
2))
                  Text
"매수인이 하자 있는 것을 알았거나 과실로 인하여 이를 알지 못한 때에는 하자담보책임을 물을 수 없다."
    | Bool
otherwise =
        Judgment rest -> Judgment (BuyerKnowledge : rest)
forall (prev :: [*]) l. Judgment prev -> Judgment (l : prev)
JDelegate (forall act (layers :: [*]).
Adjudicate act layers =>
act -> Facts act -> Judgment layers
adjudicate @_ @rest WarrantyAct
act Facts WarrantyAct
facts)