
    KCj                         d Z ddlZddlmZ ddlmZ ddlmZmZ ddl	m
Z
  e
e      Z ed      Z G d d	      Z e       Zy)
u^  
Reference data service.

Loads data/lookup/crops.json and data/lookup/districts.json ONCE at
application startup and keeps them in memory. This is deliberately not
a database table for v1 — the list of supported crops/districts changes
rarely, and a JSON file the project coordinator (or client) can edit
without touching code is the right amount of flexibility for now.

If the client later wants self-service crop/district management through
an admin UI, this becomes a database table with the exact same interface
(get_crop, get_district, list_crops, list_districts) — calling code
doesn't change.
    N)Path)Optional)UnsupportedCropErrorUnsupportedDistrictError)
get_loggerzdata/lookupc                       e Zd ZddZddZddZdedefdZdedefd	Z	de
e   fd
Zde
e   fdZdedefdZdedefdZy)ReferenceDataServicereturnNc                 .    i | _         i | _        d| _        y )NF)_crops
_districts_loadedselfs    HC:\Crop_Prediction\Backend\crop-ai-system\app\services\reference_data.py__init__zReferenceDataService.__init__   s    ')+-    c                    t         dz  }t         dz  }|j                         st        d| d      |j                         st        d| d      t        |d      5 }t	        j
                  |      | _        d d d        t        |d      5 }t	        j
                  |      | _        d d d        | j                  st        d      | j                  st        d	      d
| _	        t        j                  dt        | j                         dt        | j                         d       y # 1 sw Y   xY w# 1 sw Y   xY w)Nz
crops.jsonzdistricts.jsonzRequired lookup file missing: z3. The system cannot validate crop input without it.z7. The system cannot validate location input without it.z	utf-8-sig)encodingz'crops.json loaded but contains no cropsz/districts.json loaded but contains no districtsTzReference data loaded: z crops, z
 districts)
LOOKUP_DIRexistsFileNotFoundErroropenjsonloadr   r   
ValueErrorr   loggerinfolen)r   
crops_pathdistricts_pathfs       r   r   zReferenceDataService.load"   s9   ,.
#&66  "#0 =D E  $$&#00@ AH I  *{3 	'q))A,DK	'.;7 	+1"iilDO	+ {{FGGNOO%c$++&6%7x4??#$J0	
	' 	'	+ 	+s   D)D5)D25D>c                 2    | j                   st        d      y )NzWReferenceDataService used before load() was called. This indicates a startup-order bug.)r   RuntimeErrorr   s    r   _ensure_loadedz#ReferenceDataService._ensure_loadedE   s     ||6  r   cropc                    | j                          |j                         j                         }|| j                  vrBt	        d| ddj                  t        | j                  j                                            | j                  |   S )N'z,' is not a supported crop. Supported crops: , message)r%   striplowerr   r   joinsortedkeysr   r&   s     r   get_cropzReferenceDataService.get_cropL   s    zz|!!#t{{"&v ((,		&9I9I9K2L(M'NP  {{4  r   districtc                    | j                          |j                         j                         }|| j                  vrBt	        d| ddj                  t        | j                  j                                            | j                  |   S )Nr(   z4' is not a supported district. Supported districts: r)   r*   )r%   r,   r-   r   r   r.   r/   r0   r   r3   s     r   get_districtz!ReferenceDataService.get_districtX   s    >>#))+4??**z ",,0IIfT__=Q=Q=S6T,U+VX  x((r   c                 h    | j                          t        | j                  j                               S N)r%   r/   r   r0   r   s    r   
list_cropszReferenceDataService.list_cropsd   s&    dkk&&())r   c                 h    | j                          t        | j                  j                               S r8   )r%   r/   r   r0   r   s    r   list_districtsz#ReferenceDataService.list_districtsh   s&    doo**,--r   c                 v    | j                          |j                         j                         | j                  v S r8   )r%   r,   r-   r   r1   s     r   is_valid_cropz"ReferenceDataService.is_valid_cropl   s,    zz|!!#t{{22r   c                 v    | j                          |j                         j                         | j                  v S r8   )r%   r,   r-   r   r5   s     r   is_valid_districtz&ReferenceDataService.is_valid_districtp   s-    ~~%%'4??::r   )r
   N)__name__
__module____qualname__r   r   r%   strdictr2   r6   listr9   r;   boolr=   r?    r   r   r	   r	      s~    
!
F
!S 
!T 
!
)S 
)T 
)*DI *.S	 .3# 3$ 3;# ;$ ;r   r	   )__doc__r   pathlibr   typingr   app.core.exceptionsr   r   app.core.logging_configr   r@   r   r   r	   reference_datarG   r   r   <module>rN      sF       N .	H	- 
V; V;t &'r   