use strict;
use warnings;

our @ScripConditions;

our @CustomFields = (
    {   Name        => 'CVE ID',
        Type        => 'FreeformMultiple',
        Disabled    => 0,
        LookupType  => 'RT::Queue-RT::Ticket',
        Description => 'CVE ID for RTIR queues',
        LinkValueTo => 'https://nvd.nist.gov/vuln/detail/__CustomField__#vulnCurrentDescriptionTitle',
    },
);

our @ScripActions = (
    {   Name        => 'RTIR parse message for CVEs',                 # loc
        Description => 'Set CVE custom field from message content',   # loc
        ExecModule  => 'RTIR_FindCVE',
    },
    {   Name        => 'RTIR merge CVEs',                                 # loc
        Description => 'Merge multiple CVEs on ticket merge',             # loc
        ExecModule  => 'RTIR_MergeCVEs',
    },
);

our @Scrips = (
    {
        Description    => "SetCVEFromContent",
        Queue          => [ 'Incidents', 'Incident Reports', 'Investigations', 'Countermeasures' ],
        ScripCondition => 'On Correspond',
        ScripAction    => 'RTIR parse message for CVEs',
        Template       => 'Blank'
    },
    {
        Description    => "SetCVEFromContent",
        Queue          => [ 'Incidents', 'Incident Reports', 'Investigations', 'Countermeasures' ],
        ScripCondition => 'On Create',
        ScripAction    => 'RTIR parse message for CVEs',
        Template       => 'Blank'
    },
    {   Description => "MergeCVEs",
        Queue =>
            [ 'Incidents', 'Incident Reports', 'Investigations', 'Countermeasures' ],
        ScripCondition => 'RTIR Merge',
        ScripAction    => 'RTIR merge CVEs',
        Template       => 'Blank'
    },
    {   Description    => "On Linking To Incident Copy CVEs",
        Queue          => 'Incident Reports',
        ScripCondition => 'RTIR Linking To Incident',
        ScripAction    => 'RTIR merge CVEs',
        Template       => 'Blank'
    },
);

our @Final = (
    sub {
        RT->Logger->debug("Converting homepages to dashboards");
        my $attrs = RT::Attributes->new( RT->SystemUser );
        $attrs->Limit( FIELD => 'Name', VALUE => [ 'Pref-RTIR_HomepageSettings', 'RTIR_HomepageSettings' ], OPERATOR => 'IN' );
    OUTER: while ( my $attr = $attrs->Next ) {
            my $attr_id = $attr->Id;
            my $object  = $attr->Object;
            my $content = $attr->Content;

            if ( $object && ( $object->isa('RT::User') || $object->isa('RT::System') ) && $content ) {
                my $dashboard = RT::Dashboard->new( RT->SystemUser );
                my $panes     = {};

                for my $pane ( sort keys %$content ) {
                    my $list = $content->{$pane} or next;
                    for my $entry (@$list) {
                        my $new_entry = { pane => $pane };
                        if ( $entry->{type} eq 'system' ) {
                            if ( my $name = $entry->{name} ) {
                                my ($search)
                                    = RT::System->new( RT->SystemUser )->Attributes->Named( 'Search - ' . $name );

                                # Check user created system searches
                                if ( !$search ) {
                                    my (@searches)
                                        = RT::System->new( RT->SystemUser )->Attributes->Named('SavedSearch');
                                    for my $custom (@searches) {
                                        if ( $custom->Description eq $entry->{name} ) {
                                            $search = $custom;
                                            last;
                                        }
                                    }
                                }

                                if ( $search ) {
                                    $new_entry->{portlet_type} = 'search';
                                    $new_entry->{id}           = $search->Id;
                                    $new_entry->{description}  = "Saved Search: $name";
                                    $new_entry->{privacy}      = 'RT::System-1';
                                }
                                else {
                                    RT->Logger->warning(
                                        "System search $name in attribute #$attr_id not found, skipping");
                                    next;
                                }
                            }
                            else {
                                RT->Logger->warning("Missing system search name in attribute #$attr_id, skipping");
                                next;
                            }
                        }
                        elsif ( $entry->{type} eq 'saved' ) {
                            if ( my $name = $entry->{name} ) {
                                if ( $name =~ /(.+)-SavedSearch-(\d+)/ ) {
                                    $new_entry->{privacy}      = $1;
                                    $new_entry->{id}           = $2;
                                    $new_entry->{portlet_type} = 'search';
                                    my $search = RT::Attribute->new( RT->SystemUser );
                                    $search->Load( $new_entry->{id} );
                                    if ( $search->Id ) {
                                        $new_entry->{description} = "Saved Search: " . $search->Description;
                                    }
                                    else {
                                        RT->Logger->warning(
                                            "Saved search $name in attribute #$attr_id not found, skipping");
                                        next;
                                    }
                                }
                                else {
                                    RT->Logger->warning(
                                        "System search $name in attribute #$attr_id not found, skipping");
                                    next;
                                }
                            }
                            else {
                                RT->Logger->warning("Missing system search name in attribute #$attr_id, skipping");
                                next;
                            }
                        }
                        elsif ( $entry->{type} eq 'component' ) {
                            $new_entry->{portlet_type} = 'component';
                            $new_entry->{component}    = $entry->{name};
                            $new_entry->{description}  = $entry->{name};
                            $new_entry->{path}         = $entry->{name} =~ m{^/} ? $entry->{name} : "/Elements/$entry->{name}";
                        }
                        else {
                            RT->Logger->warning("Unsupported type $entry->{type} in attribute #$attr_id, skipping");
                            next;
                        }
                        push @{$panes->{$pane}}, $new_entry;
                    }
                }

                $RT::Handle->BeginTransaction;
                my %new_values = (
                    'Name'        => 'Dashboard',
                    'Description' => 'RTIR Homepage',
                    'Content'     => { Panes => $panes },
                );

                for my $field ( sort keys %new_values ) {
                    my $method = "Set$field";
                    my ( $ret, $msg ) = $attr->$method( $new_values{$field} );
                    if ( !$ret ) {
                        RT->Logger->error("Couldn't update $field of attribute #$attr_id: $msg");
                        $RT::Handle->Rollback;
                        next OUTER;
                    }
                }

                my ( $id, $msg ) = $object->SetAttribute(
                    'Name'        => $object->isa('RT::User') ? 'Pref-RTIRDefaultDashboard' : 'RTIRDefaultDashboard',
                    'Description' => 'RTIR Default Dashboard',
                    'Content'     => $attr_id,
                );
                if ($id) {
                    $RT::Handle->Commit;
                }
                else {
                    RT->Logger->error("Couldn't set DefaultDashboard to $id for attribute #$attr_id: $msg");
                    $RT::Handle->Rollback;
                }
            }
        }
    },
    sub {
        my $attrs = RT::Attributes->new( RT->SystemUser );
        $attrs->Limit(
            FIELD    => 'Name',
            VALUE    => [ 'RTIRDefaultDashboard', 'Pref-RTIRDefaultDashboard' ],
            OPERATOR => 'IN',
        );
        while ( my $attr = $attrs->Next ) {
            my ( $ret, $msg ) = $attr->_SyncLinks;
            if ( !$ret ) {
                die "Couldn't sync links for attribute #" . $attr->id . ": $msg";
            }
        }
    },
    sub {
        my $class = RT::Class->new( RT->SystemUser );
        $class->Load('Templates');
        if ( $class->Id ) {
            my $content = RT::CustomField->new( RT->SystemUser );
            $content->LoadByName( Name => 'Content', LookupType => RT::Article->CustomFieldLookupType );
            if ( $content->Id && ( $content->IsGlobal || $content->IsAdded( $class->Id ) ) ) {
                for ( 'CF-Title-' . $content->Id, 'CF-Value-' . $content->Id ) {
                    $class->SetAttribute( Name => "Skip-$_", Content => 1 );
                }
            }
        }
    },
    sub {
        # Apply new CVE ID CF to existing RTIR queues based on lifecycle
        my $cve_id_obj = RT::CustomField->new(RT->SystemUser);
        my ($ok, $msg) = $cve_id_obj->LoadByName( Name => 'CVE ID' );

        if ( $cve_id_obj->IsGlobal ) {
            my $empty_queue = RT::Queue->new( RT->SystemUser );
            my ($ok, $msg) = $cve_id_obj->RemoveFromObject( $empty_queue );
        }

        if ( $ok && $cve_id_obj->Id ) {
            my $queues = RT::Queues->new(RT->SystemUser);
            $queues->Limit( FIELD => 'Lifecycle', VALUE => [ 'incident_reports', 'incidents', 'investigations', 'countermeasures' ], OPERATOR => 'IN' );
            while ( my $queue = $queues->Next ) {
                my ($ok, $msg) = $cve_id_obj->AddToObject( $queue );
                RT->Logger->error("Unable to apply CVE ID to queue " . $queue->Name . " $msg") unless $ok;
            }
        }
        else {
            RT->Logger->error("Unable to load custom field CVE ID: $msg");
        }
    },
);

1;
