# (rts) PS C:\Github\siggen> python .\Scripts\fetch_tables.py
import pandas as pd
import pyodbc
import os, json, csv
from tqdm import tqdm
from datetime import datetime

starting_time = datetime.now()

# 루트폴더 지정
path_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
with open(os.path.join(path_root, 'Scripts', 'config.json'), 'r') as config_file:
    config = json.load(config_file)

# 주요 폴더 경로 지정
paths = config['paths']
path_tables = os.path.join(path_root, *paths['tables'])
path_results = os.path.join(path_root, *paths['results'])

# 이슈사항 목록
issues = []

# DB 접속정보
connection_info = config['connection_info']
DSNNAME = connection_info["DSNNAME"]
DBUSER = connection_info["DBUSER"]
DBPWD = connection_info["DBPWD"]

# 오류 발생을 위한 코드
# DSNNAME += 'a'
# DBUSER += 'a'
# DBPWD += 'a'

# 데이터베이스 연결
try:
    cnxn = pyodbc.connect(f'DSN={DSNNAME};UID={DBUSER};PWD={DBPWD};charset=utf-8')
    cursor = cnxn.cursor()
    print("데이터베이스 연결에 성공했습니다.")
except pyodbc.InterfaceError:
    print("데이터베이스 연결 실패: 데이터 원본 이름을 확인하거나 기본 드라이버를 지정하세요.")
    # 여기서 오류 처리 로직을 추가할 수 있습니다.
except pyodbc.OperationalError as e:
    if "Login failed" in str(e):
        print("로그인 실패: 사용자 이름 또는 비밀번호가 유효하지 않습니다.")
    else:
        print("연결 실패: 운영 체제 레벨에서 오류가 발생했습니다.")
    # 여기서 오류 처리 로직을 추가할 수 있습니다.
except Exception as e:
    print(f"예기치 않은 오류가 발생했습니다: {e}")
    # 여기서 오류 처리 로직을 추가할 수 있습니다.


schema = 'SNITS_INT'
tables = ['S_INT_CONFIG', # 교차로 제어기
          'S_INT_PHASE_CONFIG', # 교차로 현시구성
          'S_INT_TPLAN', # 교차로 시간계획
          'S_SA_CYCLE_PLAN',
          'S_SA_DPLAN', # 그룹 일계획
          'S_SA_WPLAN', # 그룹 주간계획
          'S_TOD_HIS'] # 신호 TOD 이력

# 폴더 Data\tables\yyyymmdd_hhmmss 생성
timestamp = starting_time.strftime('%Y%m%d_%H%M%S')
# base_dir = os.path.join(path_tables, timestamp)
os.makedirs(os.path.join(path_tables, timestamp), exist_ok=True)

def fetch_table(table, condition=""):
    try:
        query = f"SELECT * FROM {schema}.{table} {condition}"
        cursor.execute(query)
        csv_file_path = os.path.join(path_tables, timestamp, f"{table}.csv")
        with open(csv_file_path, 'w', newline='', encoding='utf-8-sig') as csvfile:
            csv_writer = csv.writer(csvfile)
            columns = [column[0] for column in cursor.description]
            csv_writer.writerow(columns)
            for row in cursor.fetchall():
                csv_writer.writerow(row)
    except pyodbc.ProgrammingError as e:
        if '42S02' in str(e):
            print(f"오류: '{table}' 테이블이 스키마에 존재하지 않습니다.")
        else:
            print(f"SQL 실행 오류: {e}")
    except Exception as e:
        print(f"예기치 않은 오류가 발생했습니다: {e}")

fetch_table('S_INT_CONFIG')
fetch_table('S_INT_PHASE_CONFIG')
fetch_table('S_INT_TPLAN')
fetch_table('S_SA_CYCLE_PLAN')
fetch_table('S_SA_DPLAN')
fetch_table('S_SA_WPLAN')
fetch_table('S_TOD_HIS', condition="WHERE INT_CREATE_DATE >= TO_TIMESTAMP('2023-10-17 23:15:00.0') ORDER BY INT_NO ASC, INT_CREATE_DATE DESC;")
# 오류 발생을 위한 코드
fetch_table('foo')
print("테이블을 모두 불러왔습니다.")

cnxn.close()

inter_info = pd.read_csv(os.path.join(path_tables, timestamp, 'S_INT_CONFIG.csv'))
plan = pd.read_csv(os.path.join(path_tables, timestamp, 'S_INT_TPLAN.csv'))
history = pd.read_csv(os.path.join(path_tables, timestamp, 'S_TOD_HIS.csv'))
print(inter_info)
print(plan)
print(history)

# 1-4-2. 교차로정보(inter_info) 검사
def check_inter_info():
    # 1-4-2-1. inter_lat, inter_lon 적절성 검사
    inter_info.loc[0, 'INT_LAT'] = 38.0 # 에러 발생을 위한 코드
    max_lon, min_lon = 127.3, 127.0
    max_lat, min_lat = 37.5, 37.2
    for _, row in inter_info.iterrows():
        latbool = min_lat <= row['INT_LAT'] <= max_lat
        lonbool = min_lon <= row['INT_LNG'] <= max_lon
        if not(latbool and lonbool):
            msg = f"1-4-2-1. 위도 또는 경도가 범위를 벗어난 교차로가 있습니다: INT_NO : {row['INT_NO']}"
            issues.append(msg)

def write_issues():
    print('3. 이슈사항을 저장합니다.')
    path_issues = os.path.join(path_results, "issues_fetch_tables.txt")
    with open(path_issues, "w", encoding="utf-8") as file:
        for item in issues:
            file.write(item + "\n")
    if issues:
        print("데이터 처리 중 발생한 특이사항은 다음과 같습니다. :")
        for review in issues:
            print(review)
check_inter_info()
write_issues()

print("elapsed time :", datetime.now() - starting_time)