﻿USE [msdb];
GO

CREATE OR ALTER PROCEDURE dbo.usp_CreateWeeklySchedules
    @Env VARCHAR(10) = 'DEVL'  -- Added parameter with default value
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE 
        @JobName SYSNAME,
        @FrequencyPattern NVARCHAR(MAX),
        @StartTime VARCHAR(50),
        @ScheduleName SYSNAME,
        @StartTimeInt INT,
        @FreqInterval INT,
        @ActiveDate INT,
        @computedFreq INT,
        @dbName SYSNAME;  -- Added variable for database name

    -- Determine database name based on environment
    SET @dbName = CASE @Env
                    WHEN 'DEVL' THEN 'DevlDUTASJobSchedule'
                    WHEN 'TEST' THEN 'TestDUTASJobSchedule'
                    WHEN 'PROD' THEN 'ProdDUTASJobSchedule'
                  END;

    SET @ActiveDate = CONVERT(INT, CONVERT(CHAR(8), GETDATE(), 112));

    --------------------------------------------------------------------------
    -- Dynamic SQL for cursor to fetch active weekly jobs from appropriate database
    --------------------------------------------------------------------------
    DECLARE @Sql NVARCHAR(MAX);
    SET @Sql = N'
    DECLARE job_cursor CURSOR FAST_FORWARD FOR
    SELECT 
        JobName, 
        FrequencyPattern, 
        ScheduledStartTime
    FROM ' + QUOTENAME(@dbName) + N'.dbo.JobControl
    WHERE UPPER(Frequency) = ''WEEKLY''
      AND IsActive = 1;';

    -- Execute dynamic SQL to declare cursor
    EXEC sp_executesql @Sql;

    OPEN job_cursor;
    FETCH NEXT FROM job_cursor INTO @JobName, @FrequencyPattern, @StartTime;

    WHILE @@FETCH_STATUS = 0
    BEGIN
        BEGIN TRY
            ------------------------------------------------------------------
            -- Reset per-job variables
            ------------------------------------------------------------------
            SET @FreqInterval = 0;
            SET @computedFreq = 0;
            SET @StartTimeInt = NULL;
            SET @ScheduleName = NULL;

            ------------------------------------------------------------------
            -- Correctly format the start time (HHMMSS without extra zeros)
            ------------------------------------------------------------------
            SET @StartTime = LTRIM(RTRIM(ISNULL(@StartTime, '00:00:00')));
            
            -- Parse time and convert to HHMMSS integer
            DECLARE @TimeParts TABLE (part NVARCHAR(10), idx INT);
            INSERT INTO @TimeParts (part, idx)
            SELECT value, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1
            FROM STRING_SPLIT(LEFT(@StartTime, 8), ':');
            
            DECLARE @Hours INT, @Minutes INT, @Seconds INT;
            
            SELECT @Hours = CAST(part AS INT) FROM @TimeParts WHERE idx = 0;
            SELECT @Minutes = CAST(part AS INT) FROM @TimeParts WHERE idx = 1;
            SELECT @Seconds = CAST(part AS INT) FROM @TimeParts WHERE idx = 2;
            
            -- Ensure valid time ranges
            SET @Hours = ISNULL(@Hours, 0);
            SET @Minutes = ISNULL(@Minutes, 0);
            SET @Seconds = ISNULL(@Seconds, 0);
            
            IF @Hours < 0 OR @Hours > 23 SET @Hours = 0;
            IF @Minutes < 0 OR @Minutes > 59 SET @Minutes = 0;
            IF @Seconds < 0 OR @Seconds > 59 SET @Seconds = 0;
            
            SET @StartTimeInt = (@Hours * 10000) + (@Minutes * 100) + @Seconds;

            SET @ScheduleName = CONCAT(@JobName, '_WeeklySchedule');

            ------------------------------------------------------------------
            -- Parse JSON days using a local temporary table
            ------------------------------------------------------------------
            CREATE TABLE #Days (DayName NVARCHAR(10));
            
            INSERT INTO #Days (DayName)
            SELECT TRIM(value)
            FROM OPENJSON(ISNULL(@FrequencyPattern, '{}'), '$.Days');

            ------------------------------------------------------------------
            -- Compute bitmask correctly (values should be 1-127)
            ------------------------------------------------------------------
            SELECT @computedFreq = ISNULL(SUM(
                CASE UPPER(DayName)
                    WHEN 'SUN' THEN 1
                    WHEN 'MON' THEN 2
                    WHEN 'TUE' THEN 4
                    WHEN 'WED' THEN 8
                    WHEN 'THU' THEN 16
                    WHEN 'FRI' THEN 32
                    WHEN 'SAT' THEN 64
                    ELSE 0
                END
            ), 0)
            FROM #Days;

            DROP TABLE #Days; -- Explicitly drop the temp table

            SET @FreqInterval = ISNULL(@computedFreq, 0);

            ------------------------------------------------------------------
            -- Validate freq_interval (must be 1..127)
            ------------------------------------------------------------------
            IF @FreqInterval < 1 OR @FreqInterval > 127
            BEGIN
                PRINT 'Warning: Weekly job ' + @JobName + 
                      ' has invalid freq_interval (' + ISNULL(CAST(@FreqInterval AS VARCHAR(10)), 'NULL') + 
                      '). Days found: ' + ISNULL(@FrequencyPattern, 'None') + '. Skipping.';
                FETCH NEXT FROM job_cursor INTO @JobName, @FrequencyPattern, @StartTime;
                CONTINUE;
            END

            ------------------------------------------------------------------
            -- Debug output to verify calculations
            ------------------------------------------------------------------
            PRINT 'Job: ' + @JobName + 
                  ', Days: ' + @FrequencyPattern +
                  ', FreqInterval: ' + CAST(@FreqInterval AS VARCHAR(3)) +
                  ', StartTime: ' + CAST(@StartTimeInt AS VARCHAR(6));

            ------------------------------------------------------------------
            -- Safely detach and delete any existing schedule with this name
            -- Use TRY/CATCH for schedule operations since non-existence is expected
            ------------------------------------------------------------------
            BEGIN TRY
                DECLARE @schedule_id INT;
                DECLARE @attach_count INT;

                -- Check if schedule exists and get its ID
                SELECT @schedule_id = s.schedule_id
                FROM msdb.dbo.sysschedules s
                JOIN msdb.dbo.sysjobschedules js ON s.schedule_id = js.schedule_id
                JOIN msdb.dbo.sysjobs j ON j.job_id = js.job_id
                WHERE j.name = @JobName AND s.name = @ScheduleName;

                IF @schedule_id IS NOT NULL
                BEGIN
                    -- Detach from this job (if attached)
                    EXEC msdb.dbo.sp_detach_schedule 
                        @job_name = @JobName, 
                        @schedule_name = @ScheduleName;

                    -- Check if schedule still attached to other jobs
                    SELECT @attach_count = COUNT(*) 
                    FROM msdb.dbo.sysjobschedules js
                    WHERE js.schedule_id = @schedule_id;

                    IF @attach_count = 0
                    BEGIN
                        EXEC msdb.dbo.sp_delete_schedule 
                            @schedule_name = @ScheduleName;
                        PRINT 'Existing schedule deleted: ' + @ScheduleName;
                    END
                    ELSE
                    BEGIN
                        PRINT 'Notice: schedule ' + @ScheduleName + ' could not be deleted because it is still attached to other jobs.';
                    END
                END
            END TRY
            BEGIN CATCH
                -- Schedule operations might fail if schedule doesn't exist, which is fine
                PRINT 'Notice: ' + ERROR_MESSAGE() + ' - proceeding with new schedule creation.';
            END CATCH

            ------------------------------------------------------------------
            -- Create the unified weekly schedule with subday config
            ------------------------------------------------------------------
            EXEC msdb.dbo.sp_add_schedule
                @schedule_name = @ScheduleName,
                @enabled = 1,
                @freq_type = 8,                  -- Weekly
                @freq_interval = @FreqInterval,  -- Bitmask of weekdays
                @freq_recurrence_factor = 1,     -- Every week
                @freq_subday_type = 1,           -- Once per day
                @freq_subday_interval = 1,
                @active_start_time = @StartTimeInt,
                @active_start_date = @ActiveDate;

            ------------------------------------------------------------------
            -- Attach the schedule to the job
            ------------------------------------------------------------------
            EXEC msdb.dbo.sp_attach_schedule
                @job_name = @JobName,
                @schedule_name = @ScheduleName;

            PRINT 'Weekly schedule created for job: ' + @JobName + 
                  ' (Days=' + CAST(@FreqInterval AS VARCHAR(10)) + 
                  ', Time=' + RIGHT('000000' + CAST(@StartTimeInt AS VARCHAR(6)), 6) + ')';

        END TRY
        BEGIN CATCH
            PRINT 'Error scheduling job ' + ISNULL(@JobName, 'Unknown') + ': ' + ERROR_MESSAGE();
        END CATCH;

        FETCH NEXT FROM job_cursor INTO @JobName, @FrequencyPattern, @StartTime;
    END

    CLOSE job_cursor;
    DEALLOCATE job_cursor;

    PRINT 'All weekly job schedules processed for ' + @dbName;
END;
GO