{-# LANGUAGE LambdaCase #-}
-- | Omnibus evaluator: runs all act types against a unified set of facts.
--
-- Given a 'CaseFacts', 'evaluateAll' constructs every applicable act type,
-- queries the framework, and returns all relevant results. The only human
-- input is the fact mapping; everything else is mechanical.
module Deontic.Civil.Evaluate
  ( CaseFacts(..)
  , CaseResult(..)
  , evaluateAll
  , defaultCaseFacts
  , domainFact
  ) where

import Data.Functor.Identity (Identity(..))
import Data.Maybe (catMaybes)
import Data.Text (Text)
import qualified Data.Set as Set
import qualified Data.Dependent.Map as DMap

import Deontic.Core.Types (PersonId, ActId, ArticleRef(..))
import Deontic.Core.Adjudicate
import Deontic.Civil.Types

-- Bring instances into scope
import Deontic.Civil.Persons ()
import Deontic.Civil.Acts ()
import Deontic.Civil.Agency ()
import Deontic.Civil.Possession ()
import Deontic.Civil.Prescription ()
import Deontic.Civil.CoOwnership ()
import Deontic.Civil.Tort ()
import Deontic.Civil.Rescission ()
import Deontic.Civil.PropertyTransfer ()
import Deontic.Civil.AcquisitivePrescription ()
import Deontic.Civil.DefaultObligation ()
import Deontic.Civil.SaleWarranty ()
import Deontic.Civil.Lease ()
import Deontic.Civil.AgencyRemedies ()
import Deontic.Civil.Invalidity ()
import Deontic.Civil.Cancellation ()
import Deontic.Civil.ConditionalAct ()

-- | Unified case facts. The omnibus input to 'evaluateAll'.
--
-- Boolean/flag facts go in 'cfCivilFacts'. Structured facts for
-- domain-specific act types are stored in a 'DMap.DMap' keyed by
-- 'DomainKey' — only provided when the case involves that legal issue.
data CaseFacts = CaseFacts
  { CaseFacts -> PersonId
cfActor        :: PersonId          -- ^ 행위자/표의자
  , CaseFacts -> Maybe PersonId
cfCounterparty :: Maybe PersonId    -- ^ 상대방 (agency, tort)
  , CaseFacts -> ActId
cfActId        :: ActId             -- ^ 행위 식별자
  , CaseFacts -> Set CivilFact
cfCivilFacts   :: Set.Set CivilFact -- ^ Boolean/flag facts
  , CaseFacts -> DMap DomainKey Identity
cfDomainFacts  :: DMap.DMap DomainKey Identity
  }

-- | Convenience constructor with all optional fields empty.
defaultCaseFacts :: PersonId -> ActId -> CaseFacts
defaultCaseFacts :: PersonId -> ActId -> CaseFacts
defaultCaseFacts PersonId
actor ActId
actId = CaseFacts
  { cfActor :: PersonId
cfActor        = PersonId
actor
  , cfCounterparty :: Maybe PersonId
cfCounterparty = Maybe PersonId
forall a. Maybe a
Nothing
  , cfActId :: ActId
cfActId        = ActId
actId
  , cfCivilFacts :: Set CivilFact
cfCivilFacts   = Set CivilFact
forall a. Set a
Set.empty
  , cfDomainFacts :: DMap DomainKey Identity
cfDomainFacts  = DMap DomainKey Identity
forall {k1} (k2 :: k1 -> *) (f :: k1 -> *). DMap k2 f
DMap.empty
  }

-- | Insert a domain-specific fact record into a 'CaseFacts'.
domainFact :: DomainKey a -> a -> CaseFacts -> CaseFacts
domainFact :: forall a. DomainKey a -> a -> CaseFacts -> CaseFacts
domainFact DomainKey a
k a
v CaseFacts
cf = CaseFacts
cf { cfDomainFacts = DMap.insert k (Identity v) (cfDomainFacts cf) }

-- | Look up a domain fact.
lookupDomain :: DomainKey a -> CaseFacts -> Maybe a
lookupDomain :: forall a. DomainKey a -> CaseFacts -> Maybe a
lookupDomain DomainKey a
k CaseFacts
cf = Identity a -> a
forall a. Identity a -> a
runIdentity (Identity a -> a) -> Maybe (Identity a) -> Maybe a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DomainKey a -> DMap DomainKey Identity -> Maybe (Identity a)
forall {k1} (k2 :: k1 -> *) (f :: k1 -> *) (v :: k1).
GCompare k2 =>
k2 v -> DMap k2 f -> Maybe (f v)
DMap.lookup DomainKey a
k (CaseFacts -> DMap DomainKey Identity
cfDomainFacts CaseFacts
cf)

-- | A single evaluation result.
data CaseResult = CaseResult
  { CaseResult -> Text
crLabel    :: Text           -- ^ Human-readable label (e.g., "미성년자 (§5)")
  , CaseResult -> SomeJudgment
crJudgment :: SomeJudgment   -- ^ The full judgment
  }

-- | Run all act types against the case facts.
-- Returns all results for relevant (guarded) act types, including
-- trivially valid ones — so the output shows every act type that was
-- checked, not just those with non-trivial verdicts.
--
-- Act types with unconditional base verdicts (ShamAct → always Void,
-- MistakeAct → always Voidable, etc.) require a trigger fact to be
-- present, because selecting that act type IS the relevant fact in the
-- real legal analysis.
evaluateAll :: CaseFacts -> [CaseResult]
evaluateAll :: CaseFacts -> [CaseResult]
evaluateAll CaseFacts
cf = [Maybe CaseResult] -> [CaseResult]
forall a. [Maybe a] -> [a]
catMaybes
  -- ── Set CivilFact act types ──
  -- MinorAct: relevant if IsMinor is present
  [ Bool -> CaseResult -> Maybe CaseResult
guarded (Set CivilFact -> Bool
anyMinor (CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf)) (CaseResult -> Maybe CaseResult) -> CaseResult -> Maybe CaseResult
forall a b. (a -> b) -> a -> b
$ Text -> Judgment '[Proviso, Base] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"미성년자 (§5)"
      (MinorAct -> Facts MinorAct -> Judgment (Resolvable MinorAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (PersonId -> ActId -> MinorAct
MinorAct (CaseFacts -> PersonId
cfActor CaseFacts
cf) (CaseFacts -> ActId
cfActId CaseFacts
cf)) (CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf))
  -- JuristicAct: relevant if any §103-107 trigger present
  , Bool -> CaseResult -> Maybe CaseResult
guarded ([CivilFact] -> Set CivilFact -> Bool
hasAny [CivilFact
ContraBonorsMores, CivilFact
ExploitativeAct, CivilFact
HiddenIntention] (CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf))
      (CaseResult -> Maybe CaseResult) -> CaseResult -> Maybe CaseResult
forall a b. (a -> b) -> a -> b
$ Text -> Judgment '[SpecialRule, Proviso, Base] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"법률행위 (§103-107)"
      (JuristicAct
-> Facts JuristicAct -> Judgment (Resolvable JuristicAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (PersonId -> ActId -> JuristicAct
JuristicAct (CaseFacts -> PersonId
cfActor CaseFacts
cf) (CaseFacts -> ActId
cfActId CaseFacts
cf)) (CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf))
  -- ShamAct: always Void, only relevant if explicitly indicated
  , Bool -> CaseResult -> Maybe CaseResult
guarded (CivilFact
BonaFideThirdParty CivilFact -> Set CivilFact -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf)
      (CaseResult -> Maybe CaseResult) -> CaseResult -> Maybe CaseResult
forall a b. (a -> b) -> a -> b
$ Text -> Judgment '[Proviso, Base] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"통정허위표시 (§108)"
      (ShamAct -> Facts ShamAct -> Judgment (Resolvable ShamAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (PersonId -> ActId -> ShamAct
ShamAct (CaseFacts -> PersonId
cfActor CaseFacts
cf) (CaseFacts -> ActId
cfActId CaseFacts
cf)) (CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf))
  -- MistakeAct: relevant if GrossNegligence is present (mistake is the issue)
  , Bool -> CaseResult -> Maybe CaseResult
guarded (CivilFact
GrossNegligence CivilFact -> Set CivilFact -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf)
      (CaseResult -> Maybe CaseResult) -> CaseResult -> Maybe CaseResult
forall a b. (a -> b) -> a -> b
$ Text -> Judgment '[Proviso, Base] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"착오 (§109)"
      (MistakeAct -> Facts MistakeAct -> Judgment (Resolvable MistakeAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (PersonId -> ActId -> MistakeAct
MistakeAct (CaseFacts -> PersonId
cfActor CaseFacts
cf) (CaseFacts -> ActId
cfActId CaseFacts
cf)) (CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf))
  -- FraudAct: relevant if any §110 trigger present
  , Bool -> CaseResult -> Maybe CaseResult
guarded ([CivilFact] -> Set CivilFact -> Bool
hasAny [CivilFact
ThirdPartyFraud, CivilFact
CounterpartyKnewFraud] (CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf))
      (CaseResult -> Maybe CaseResult) -> CaseResult -> Maybe CaseResult
forall a b. (a -> b) -> a -> b
$ Text -> Judgment '[Proviso, Base] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"사기·강박 (§110)"
      (FraudAct -> Facts FraudAct -> Judgment (Resolvable FraudAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (PersonId -> ActId -> FraudAct
FraudAct (CaseFacts -> PersonId
cfActor CaseFacts
cf) (CaseFacts -> ActId
cfActId CaseFacts
cf)) (CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf))
  -- AuthAgencyAct: relevant if SelfDealing present
  , Bool -> CaseResult -> Maybe CaseResult
guarded (CivilFact
SelfDealing CivilFact -> Set CivilFact -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf)
      (CaseResult -> Maybe CaseResult) -> CaseResult -> Maybe CaseResult
forall a b. (a -> b) -> a -> b
$ Text -> Judgment '[Proviso, Base] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"유권대리 (§114, §118)"
      (AuthAgencyAct
-> Facts AuthAgencyAct -> Judgment (Resolvable AuthAgencyAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (PersonId -> PersonId -> ActId -> AuthAgencyAct
AuthAgencyAct (CaseFacts -> PersonId
cfActor CaseFacts
cf) (CaseFacts -> PersonId
agent CaseFacts
cf) (CaseFacts -> ActId
cfActId CaseFacts
cf)) (CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf))
  -- UnauthAgencyAct: relevant if any agency trigger present
  , Bool -> CaseResult -> Maybe CaseResult
guarded ([CivilFact] -> Set CivilFact -> Bool
hasAny [CivilFact
Ratified, CivilFact
IndicatedAuthority, CivilFact
ExceededScope, CivilFact
AuthorityExpired] (CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf))
      (CaseResult -> Maybe CaseResult) -> CaseResult -> Maybe CaseResult
forall a b. (a -> b) -> a -> b
$ Text -> Judgment '[ApparentAuth, Ratification, Base] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"무권대리 (§125-132)"
      (UnauthAgencyAct
-> Facts UnauthAgencyAct -> Judgment (Resolvable UnauthAgencyAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (PersonId -> PersonId -> ActId -> UnauthAgencyAct
UnauthAgencyAct (CaseFacts -> PersonId
cfActor CaseFacts
cf) (CaseFacts -> PersonId
agent CaseFacts
cf) (CaseFacts -> ActId
cfActId CaseFacts
cf)) (CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf))
  -- PossessionAct: relevant if any rebuttal fact present
  , Bool -> CaseResult -> Maybe CaseResult
guarded ([CivilFact] -> Set CivilFact -> Bool
hasAny [CivilFact
BadFaith, CivilFact
ViolentPossession, CivilFact
ClandestinePossession, CivilFact
NoOwnershipIntent] (CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf))
      (CaseResult -> Maybe CaseResult) -> CaseResult -> Maybe CaseResult
forall a b. (a -> b) -> a -> b
$ Text -> Judgment '[Rebuttal, Presumption] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"점유 추정 (§197, §200)"
      (PossessionAct
-> Facts PossessionAct -> Judgment (Resolvable PossessionAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (PersonId -> ActId -> PossessionAct
PossessionAct (CaseFacts -> PersonId
cfActor CaseFacts
cf) (CaseFacts -> ActId
cfActId CaseFacts
cf)) (CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf))
  -- PropertyTransferAct: relevant if any property transfer fact present
  , Bool -> CaseResult -> Maybe CaseResult
guarded ([CivilFact] -> Set CivilFact -> Bool
hasAny [CivilFact
HasRegistration, CivilFact
HasDelivery, CivilFact
IsRealProperty, CivilFact
IsMovableProperty,
                     CivilFact
ByInheritance, CivilFact
ByCourtOrder, CivilFact
ByPublicAuction, CivilFact
ByExpropriation] (CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf))
      (CaseResult -> Maybe CaseResult) -> CaseResult -> Maybe CaseResult
forall a b. (a -> b) -> a -> b
$ Text -> Judgment '[FormException, Base] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"물권변동 (§186-188)"
      (PropertyTransferAct
-> Facts PropertyTransferAct
-> Judgment (Resolvable PropertyTransferAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (PersonId -> ActId -> PropertyTransferAct
PropertyTransferAct (CaseFacts -> PersonId
cfActor CaseFacts
cf) (CaseFacts -> ActId
cfActId CaseFacts
cf)) (CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf))
  -- AgencyWithdrawalAct: relevant if CounterpartyKnewNoAuthority present
  , Bool -> CaseResult -> Maybe CaseResult
guarded (CivilFact
CounterpartyKnewNoAuthority CivilFact -> Set CivilFact -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf)
      (CaseResult -> Maybe CaseResult) -> CaseResult -> Maybe CaseResult
forall a b. (a -> b) -> a -> b
$ Text -> Judgment '[CounterpartyKnowledge, Base] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"상대방의 철회권 (§134)"
      (AgencyWithdrawalAct
-> Facts AgencyWithdrawalAct
-> Judgment (Resolvable AgencyWithdrawalAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (PersonId -> PersonId -> ActId -> AgencyWithdrawalAct
AgencyWithdrawalAct (CaseFacts -> PersonId
cfActor CaseFacts
cf) (CaseFacts -> PersonId
agent CaseFacts
cf) (CaseFacts -> ActId
cfActId CaseFacts
cf)) (CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf))
  -- AgentLiabilityAct: relevant if agent capacity facts present
  , Bool -> CaseResult -> Maybe CaseResult
guarded ([CivilFact] -> Set CivilFact -> Bool
hasAny [CivilFact
AgentIsLimitedCapacity, CivilFact
CounterpartyCouldHaveKnown] (CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf))
      (CaseResult -> Maybe CaseResult) -> CaseResult -> Maybe CaseResult
forall a b. (a -> b) -> a -> b
$ Text -> Judgment '[Proviso, Base] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"무권대리인의 책임 (§135)"
      (AgentLiabilityAct
-> Facts AgentLiabilityAct
-> Judgment (Resolvable AgentLiabilityAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (PersonId -> PersonId -> ActId -> AgentLiabilityAct
AgentLiabilityAct (CaseFacts -> PersonId
agent CaseFacts
cf) (CaseFacts -> PersonId
cfActor CaseFacts
cf) (CaseFacts -> ActId
cfActId CaseFacts
cf)) (CaseFacts -> Set CivilFact
cfCivilFacts CaseFacts
cf))
  -- ── Domain-record act types (run only when facts provided) ──
  , (PrescriptionFacts -> CaseResult)
-> Maybe PrescriptionFacts -> Maybe CaseResult
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\PrescriptionFacts
pf -> Text -> Judgment '[Interruption, Expiration] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"소멸시효 (§162)"
      (PrescriptionAct
-> Facts PrescriptionAct -> Judgment (Resolvable PrescriptionAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (PersonId -> ActId -> PrescriptionAct
PrescriptionAct (CaseFacts -> PersonId
cfActor CaseFacts
cf) (CaseFacts -> ActId
cfActId CaseFacts
cf)) Facts PrescriptionAct
PrescriptionFacts
pf))
      (DomainKey PrescriptionFacts -> CaseFacts -> Maybe PrescriptionFacts
forall a. DomainKey a -> CaseFacts -> Maybe a
lookupDomain DomainKey PrescriptionFacts
PrescriptionK CaseFacts
cf)
  , (TortFacts -> CaseResult) -> Maybe TortFacts -> Maybe CaseResult
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\TortFacts
tf -> Text -> Judgment '[ContributoryNeg, Base] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"불법행위 (§750, §396)"
      (TortAct -> Facts TortAct -> Judgment (Resolvable TortAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (PersonId -> PersonId -> ActId -> TortAct
TortAct (CaseFacts -> PersonId
cfActor CaseFacts
cf) (CaseFacts -> PersonId
agent CaseFacts
cf) (CaseFacts -> ActId
cfActId CaseFacts
cf)) Facts TortAct
TortFacts
tf))
      (DomainKey TortFacts -> CaseFacts -> Maybe TortFacts
forall a. DomainKey a -> CaseFacts -> Maybe a
lookupDomain DomainKey TortFacts
TortK CaseFacts
cf)
  , (CoOwnershipFacts -> CaseResult)
-> Maybe CoOwnershipFacts -> Maybe CaseResult
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\CoOwnershipFacts
cof -> Text -> Judgment '[Base] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"공유물의 처분 (§264)"
      (CoOwnershipAct
-> Facts CoOwnershipAct -> Judgment (Resolvable CoOwnershipAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (ActId -> CoOwnershipAct
CoOwnershipAct (CaseFacts -> ActId
cfActId CaseFacts
cf)) Facts CoOwnershipAct
CoOwnershipFacts
cof))
      (DomainKey CoOwnershipFacts -> CaseFacts -> Maybe CoOwnershipFacts
forall a. DomainKey a -> CaseFacts -> Maybe a
lookupDomain DomainKey CoOwnershipFacts
CoOwnershipK CaseFacts
cf)
  , (RescissionFacts -> CaseResult)
-> Maybe RescissionFacts -> Maybe CaseResult
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\RescissionFacts
rf -> Text -> Judgment '[Base] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"취소의 제척기간 (§146)"
      (RescissionAct
-> Facts RescissionAct -> Judgment (Resolvable RescissionAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (PersonId -> ActId -> RescissionAct
RescissionAct (CaseFacts -> PersonId
cfActor CaseFacts
cf) (CaseFacts -> ActId
cfActId CaseFacts
cf)) Facts RescissionAct
RescissionFacts
rf))
      (DomainKey RescissionFacts -> CaseFacts -> Maybe RescissionFacts
forall a. DomainKey a -> CaseFacts -> Maybe a
lookupDomain DomainKey RescissionFacts
RescissionK CaseFacts
cf)
  , (AcqPrescFacts -> CaseResult)
-> Maybe AcqPrescFacts -> Maybe CaseResult
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\AcqPrescFacts
apf -> Text -> Judgment '[ShortPrescription, Base] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"취득시효 (§245)"
      (AcqPrescriptionAct
-> Facts AcqPrescriptionAct
-> Judgment (Resolvable AcqPrescriptionAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (PersonId -> ActId -> AcqPrescriptionAct
AcqPrescriptionAct (CaseFacts -> PersonId
cfActor CaseFacts
cf) (CaseFacts -> ActId
cfActId CaseFacts
cf)) Facts AcqPrescriptionAct
AcqPrescFacts
apf))
      (DomainKey AcqPrescFacts -> CaseFacts -> Maybe AcqPrescFacts
forall a. DomainKey a -> CaseFacts -> Maybe a
lookupDomain DomainKey AcqPrescFacts
AcqPrescK CaseFacts
cf)
  , (DefaultFacts -> CaseResult)
-> Maybe DefaultFacts -> Maybe CaseResult
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\DefaultFacts
df -> Text -> Judgment '[CreditorDefense, Base] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"채무불이행 (§387-390)"
      (DefaultAct -> Facts DefaultAct -> Judgment (Resolvable DefaultAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (PersonId -> PersonId -> ActId -> DefaultAct
DefaultAct (CaseFacts -> PersonId
cfActor CaseFacts
cf) (CaseFacts -> PersonId
agent CaseFacts
cf) (CaseFacts -> ActId
cfActId CaseFacts
cf)) Facts DefaultAct
DefaultFacts
df))
      (DomainKey DefaultFacts -> CaseFacts -> Maybe DefaultFacts
forall a. DomainKey a -> CaseFacts -> Maybe a
lookupDomain DomainKey DefaultFacts
DefaultK CaseFacts
cf)
  , (WarrantyFacts -> CaseResult)
-> Maybe WarrantyFacts -> Maybe CaseResult
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\WarrantyFacts
wf -> Text -> Judgment '[BuyerKnowledge, Base] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"하자담보 (§580-582)"
      (WarrantyAct
-> Facts WarrantyAct -> Judgment (Resolvable WarrantyAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (PersonId -> ActId -> WarrantyAct
WarrantyAct (CaseFacts -> PersonId
cfActor CaseFacts
cf) (CaseFacts -> ActId
cfActId CaseFacts
cf)) Facts WarrantyAct
WarrantyFacts
wf))
      (DomainKey WarrantyFacts -> CaseFacts -> Maybe WarrantyFacts
forall a. DomainKey a -> CaseFacts -> Maybe a
lookupDomain DomainKey WarrantyFacts
WarrantyK CaseFacts
cf)
  , (LeaseFacts -> CaseResult) -> Maybe LeaseFacts -> Maybe CaseResult
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\LeaseFacts
lf -> Text -> Judgment '[RenewalRight, Base] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"임대차 (§618-640)"
      (LeaseAct -> Facts LeaseAct -> Judgment (Resolvable LeaseAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (PersonId -> PersonId -> ActId -> LeaseAct
LeaseAct (CaseFacts -> PersonId
cfActor CaseFacts
cf) (CaseFacts -> PersonId
agent CaseFacts
cf) (CaseFacts -> ActId
cfActId CaseFacts
cf)) Facts LeaseAct
LeaseFacts
lf))
      (DomainKey LeaseFacts -> CaseFacts -> Maybe LeaseFacts
forall a. DomainKey a -> CaseFacts -> Maybe a
lookupDomain DomainKey LeaseFacts
LeaseK CaseFacts
cf)
  , (PartialInvalidityFacts -> CaseResult)
-> Maybe PartialInvalidityFacts -> Maybe CaseResult
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\PartialInvalidityFacts
pif -> Text
-> Judgment '[Conversion, HypotheticalIntent, Base] -> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"일부무효/전환/추인 (§137-139)"
      (PartialInvalidityAct
-> Facts PartialInvalidityAct
-> Judgment (Resolvable PartialInvalidityAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (ActId -> PartialInvalidityAct
PartialInvalidityAct (CaseFacts -> ActId
cfActId CaseFacts
cf)) Facts PartialInvalidityAct
PartialInvalidityFacts
pif))
      (DomainKey PartialInvalidityFacts
-> CaseFacts -> Maybe PartialInvalidityFacts
forall a. DomainKey a -> CaseFacts -> Maybe a
lookupDomain DomainKey PartialInvalidityFacts
InvalidityK CaseFacts
cf)
  , (ConditionalFacts -> CaseResult)
-> Maybe ConditionalFacts -> Maybe CaseResult
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\ConditionalFacts
cnf -> Text
-> Judgment '[BadFaithCondition, IllegalCondition, Base]
-> CaseResult
forall {layers :: [*]}. Text -> Judgment layers -> CaseResult
cr Text
"조건부 법률행위 (§147-152)"
      (ConditionalAct
-> Facts ConditionalAct -> Judgment (Resolvable ConditionalAct)
forall act.
Adjudicate act (Resolvable act) =>
act -> Facts act -> Judgment (Resolvable act)
query (ActId -> ConditionalAct
ConditionalAct (CaseFacts -> ActId
cfActId CaseFacts
cf)) Facts ConditionalAct
ConditionalFacts
cnf))
      (DomainKey ConditionalFacts -> CaseFacts -> Maybe ConditionalFacts
forall a. DomainKey a -> CaseFacts -> Maybe a
lookupDomain DomainKey ConditionalFacts
ConditionalK CaseFacts
cf)
  ]
  where
    agent :: CaseFacts -> PersonId
agent CaseFacts
cf' = PersonId -> (PersonId -> PersonId) -> Maybe PersonId -> PersonId
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (CaseFacts -> PersonId
cfActor CaseFacts
cf') PersonId -> PersonId
forall a. a -> a
id (CaseFacts -> Maybe PersonId
cfCounterparty CaseFacts
cf')
    cr :: Text -> Judgment layers -> CaseResult
cr Text
label Judgment layers
j = Text -> SomeJudgment -> CaseResult
CaseResult Text
label (Judgment layers -> SomeJudgment
forall (layers :: [*]). Judgment layers -> SomeJudgment
SomeJudgment Judgment layers
j)

-- | Guard: include result only if condition is True.
guarded :: Bool -> CaseResult -> Maybe CaseResult
guarded :: Bool -> CaseResult -> Maybe CaseResult
guarded Bool
True  CaseResult
r = CaseResult -> Maybe CaseResult
forall a. a -> Maybe a
Just CaseResult
r
guarded Bool
False CaseResult
_ = Maybe CaseResult
forall a. Maybe a
Nothing

-- | Check if any of the given facts are present in the set.
hasAny :: [CivilFact] -> Set.Set CivilFact -> Bool
hasAny :: [CivilFact] -> Set CivilFact -> Bool
hasAny [CivilFact]
fs Set CivilFact
s = (CivilFact -> Bool) -> [CivilFact] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (CivilFact -> Set CivilFact -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` Set CivilFact
s) [CivilFact]
fs

-- | Check if any IsMinor fact is present.
anyMinor :: Set.Set CivilFact -> Bool
anyMinor :: Set CivilFact -> Bool
anyMinor = (CivilFact -> Bool) -> [CivilFact] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (\case IsMinor PersonId
_ -> Bool
True; CivilFact
_ -> Bool
False) ([CivilFact] -> Bool)
-> (Set CivilFact -> [CivilFact]) -> Set CivilFact -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Set CivilFact -> [CivilFact]
forall a. Set a -> [a]
Set.toList