Attribute VB_Name = "SQL_Generate"
Option Explicit
' ============================================================
' JUK SQL Generator
' ============================================================

Public Sub GenerateJukCsvItemDefinition(ws As Worksheet)
    Dim codePrefix As String: codePrefix = ws.CodeName
    Dim outputFileName As String: outputFileName = LCase(codePrefix) & "_csv_item_definition.sql"
    Dim csvFileName As String: csvFileName = LCase(codePrefix) & "_csv_item_definition.csv"
    
    Dim lastRow As Long: lastRow = ws.Cells(ws.Rows.Count, 4).End(xlUp).Row
    If lastRow < 9 Then
        MsgBox "No data found."
        Exit Sub
    End If
    
    Dim expectedSeq As Long: expectedSeq = 1
    Dim i As Long
    For i = 9 To lastRow
        Dim itemSeq As Long
        itemSeq = Val(Trim(CStr(ws.Cells(i, 3).Value)))
        If itemSeq = 0 Then
            lastRow = i - 1
            Exit For
        End If
        If itemSeq <> expectedSeq Then
            MsgBox "Seq error. Expected: " & expectedSeq & ", Actual: " & itemSeq & " (Row " & i & ")"
            Exit Sub
        End If
        expectedSeq = expectedSeq + 1
    Next
    
    For i = 9 To lastRow
        If Not ValidateRow(ws, i) Then Exit Sub
    Next
    
    Dim sqlHeader As String: sqlHeader = "DELETE FROM sh_csv_item_definition WHERE CODE = '" & UCase(codePrefix) & "';" & vbCrLf
    Dim sqlLines As String: sqlLines = sqlHeader
    For i = 9 To lastRow
        sqlLines = sqlLines & GenerateSqlForRow(ws, i, codePrefix) & vbCrLf
    Next
    
    If sqlLines = "" Then
        MsgBox "No data to output."
        Exit Sub
    End If
    
    Dim outputPath As String: outputPath = ThisWorkbook.Path & "\" & outputFileName
    Dim fileNum As Long: fileNum = FreeFile
    Open outputPath For Output As #fileNum
    Print #fileNum, sqlLines;
    Close #fileNum
    
    ' Generate CSV (columns matching INSERT INTO order)
    Dim csvHeader As String: csvHeader = "CODE,ITEM_SEQ,ITEM_TITLE,ITEM_NAME,IS_DUPLICATE_CHECK_KEY,DATA_TYPE,PRECISION,SCALE,NULLABLE,ENABLE_FORMAT_CHECK,FORMAT_REGEX,ENABLE_EXIST_CHECK,ALLOWED_VALUES,MASTER_SYBT,ENABLE_RELATION_CHECK,JSON_IGNORE,CMNUSER"
    Dim csvLines As String: csvLines = csvHeader & vbCrLf
    For i = 9 To lastRow
        csvLines = csvLines & GenerateCsvRow(ws, i, codePrefix) & vbCrLf
    Next
    
    Dim csvPath As String: csvPath = ThisWorkbook.Path & "\" & csvFileName
    fileNum = FreeFile
    Open csvPath For Output As #fileNum
    Print #fileNum, csvLines;
    Close #fileNum
    
    MsgBox "Files generated:" & vbCrLf & outputPath & vbCrLf & csvPath
End Sub

Private Function ValidateRow(ws As Worksheet, rowNum As Long) As Boolean
    ValidateRow = True
    
    Dim itemTitle As String: itemTitle = Trim(CStr(ws.Cells(rowNum, 4).Value))
    Dim dataType As String: dataType = Trim(CStr(ws.Cells(rowNum, 16).Value))
    Dim jsonIgnore As String: jsonIgnore = Trim(CStr(ws.Cells(rowNum, 61).Value))
    
    If itemTitle = "" Then
        MsgBox "item_title is empty. (Row " & rowNum & ")"
        ValidateRow = False
        Exit Function
    End If
    
    If dataType = "" Then
        MsgBox "data_type is empty. (Row " & rowNum & " - " & itemTitle & ")"
        ValidateRow = False
        Exit Function
    End If
    
    If jsonIgnore = "" Then
        MsgBox "json_ignore is empty. (Row " & rowNum & " - " & itemTitle & ")"
        ValidateRow = False
        Exit Function
    End If
    
    Dim allowedValues As String: allowedValues = Trim(CStr(ws.Cells(rowNum, "AA").Value))
    Dim isFormatCheck As String: isFormatCheck = Trim(CStr(ws.Cells(rowNum, "X").Value))
    
    Select Case UCase(dataType)
        Case "ENUM"
            If allowedValues = "" Then
                MsgBox "ENUM type must have allowed_values. (Row " & rowNum & " - " & itemTitle & ")"
                ValidateRow = False
                Exit Function
            End If
            If Not ValidateEnumFormat(allowedValues) Then
                MsgBox "ENUM format error. (Row " & rowNum & " - " & itemTitle & ")"
                ValidateRow = False
                Exit Function
            End If
        Case "MASTER"
            If Len(allowedValues) <> 3 Or Not IsNumeric(allowedValues) Then
                MsgBox "MASTER type must be 3-digit number. (Row " & rowNum & " - " & itemTitle & ")"
                ValidateRow = False
                Exit Function
            End If
        Case "DATE", "VARCHAR", "NUMBER"
            If isFormatCheck = "" Then
                MsgBox dataType & " type must have required. (Row " & rowNum & " - " & itemTitle & ")"
                ValidateRow = False
                Exit Function
            End If
    End Select
End Function

Private Function ValidateEnumFormat(s As String) As Boolean
    ValidateEnumFormat = False
    Dim items As Variant: items = Split(s, ", ")
    Dim i As Long
    For i = LBound(items) To UBound(items)
        Dim item As String: item = Trim(items(i))
        If item = "" Then Exit Function
        Dim parts As Variant: parts = Split(item, ":")
        If UBound(parts) <> 1 Then Exit Function
        If Not IsNumeric(parts(0)) Then Exit Function
    Next
    ValidateEnumFormat = True
End Function

Private Function GenerateSqlForRow(ws As Worksheet, rowNum As Long, codePrefix As String) As String
    Dim itemTitle As String: itemTitle = Trim(CStr(ws.Cells(rowNum, 4).Value))
    If itemTitle = "" Then
        GenerateSqlForRow = ""
        Exit Function
    End If
    
    Dim itemSeq As Long: itemSeq = Val(Trim(CStr(ws.Cells(rowNum, 3).Value)))
    Dim dataType As String: dataType = Trim(CStr(ws.Cells(rowNum, 16).Value))
    Dim allowedValues As String: allowedValues = Trim(CStr(ws.Cells(rowNum, 27).Value))
    
    ' Parse data_type (e.g. VARCHAR(60) -> dataType='VARCHAR', precision=60)
    Dim precision As String: precision = "NULL"
    Dim vScale As String: vScale = "NULL"
    Dim dtType As String: dtType = dataType
    Dim pos As Long
    Dim nums As String
    
    If InStr(dataType, "(") > 0 Then
        pos = InStr(dataType, "(")
        dtType = Trim(Left(dataType, pos - 1))
        nums = Mid(dataType, pos + 1)
        nums = Trim(Left(nums, InStr(nums, ")") - 1))
        precision = nums
        If InStr(UCase(dataType), "NUMBER") > 0 And InStr(nums, ",") > 0 Then
            precision = Trim(Mid(nums, 1, InStr(nums, ",") - 1))
            vScale = Trim(Mid(nums, InStr(nums, ",") + 1))
        End If
    End If
    
    Dim isPk As String: isPk = SqlBool(GetIsChecked(ws, rowNum, "V"))
    Dim isRequired As String: isRequired = SqlBool(GetIsChecked(ws, rowNum, "W"))
    Dim isFormatCheck As String: isFormatCheck = SqlBool(GetIsChecked(ws, rowNum, "X"))
    Dim isExistCheck As String: isExistCheck = SqlBool(GetIsChecked(ws, rowNum, "Y"))
    Dim isRelationCheck As String: isRelationCheck = SqlBool(GetIsChecked(ws, rowNum, "Z"))
    Dim isJsonIgnore As String: isJsonIgnore = SqlBool(GetIsChecked(ws, rowNum, "BI"))
    
    Dim code As String: code = "'" & UCase(codePrefix) & "'"
    Dim itemTitleStr As String: itemTitleStr = SqlString(itemTitle)
    Dim dataTypeStr As String: dataTypeStr = SqlString(dtType)
    
    ' For MASTER type, store in MASTER_SYBT; for others, store in ALLOWED_VALUES
    Dim allowedValuesStr As String
    Dim masterSybt As String
    If UCase(dtType) = "MASTER" Then
        masterSybt = "'" & allowedValues & "'"
        allowedValuesStr = "NULL"
    Else
        masterSybt = "NULL"
        If allowedValues = "" Then
            allowedValuesStr = "NULL"
        Else
            allowedValuesStr = "'{" & allowedValues & "}'"
        End If
    End If
    Dim cmnuser As String: cmnuser = "'updsv7'"
    Dim dmndate As String: dmndate = "CURRENT_TIMESTAMP"
    
    Dim nullable As String: nullable = IIf(isRequired = "TRUE", "FALSE", "TRUE")
    
    GenerateSqlForRow = "INSERT INTO SH_CSV_ITEM_DEFINITION VALUES (" & _
        code & ", " & itemSeq & ", " & itemTitleStr & ", '', " & isPk & ", " & dataTypeStr & ", " & _
        precision & ", " & vScale & ", " & nullable & ", " & isFormatCheck & ", '', " & isExistCheck & ", " & _
        allowedValuesStr & ", " & masterSybt & ", " & isRelationCheck & ", " & isJsonIgnore & ", " & cmnuser & ", " & dmndate & ");"
End Function

Private Function SqlBool(b As Boolean) As String
    SqlBool = IIf(b, "TRUE", "FALSE")
End Function

Private Function GetIsChecked(ws As Worksheet, rowNum As Long, colNumOrLetter As Variant) As Boolean
    Dim colNum As Long
    If VarType(colNumOrLetter) = vbString Then
        colNum = ws.Range(colNumOrLetter & "1").Column
    Else
        colNum = CLng(colNumOrLetter)
    End If
    Dim val As String: val = Trim(CStr(ws.Cells(rowNum, colNum).Value))
    If val = "" Or val = "FALSE" Then 
        GetIsChecked = False
    Else
        GetIsChecked = True
    End If
End Function

Private Function SqlString(s As String) As String
    If s = "" Then
        SqlString = "NULL"
    Else
        SqlString = "'" & Replace(s, "'", "''") & "'"
    End If
End Function